it-swarm.com.de

Wie kann man Benutzer mit allen Tags abfragen, wenn nach mehreren Tags gesucht wird?

Ich habe dieses benutzerdefinierte Modul, das alle Kontakte basierend auf einigen Tags anzeigt. Ich kann ein oder mehrere Tags in ein Feld im Modul einfügen

Was ich möchte, ist die Option im Modul hinzuzufügen, um Folgendes anzuzeigen:

  1. alle Kontakte mit ALLEN Tags, wie im Modul angegeben

oder

  1. alle Kontakte mit einem oder mehreren Tags, wie im Modul angegeben

Der Code, den ich gerade habe, tut das letztere. Wie kann ich die Möglichkeit für Option 1 hinzufügen?

Der Code, den ich habe, ist:

public static function getPeopleByTags($params)
{
  //echo "<pre>";
  $tags = $params->get("tags");

  $model = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true)); //load fields model

  //get people info from database
  $db = JFactory::getDbo();
  $query = $db->getQuery(true);
  $query->select('id,catid,name,alias,image,email_to,published,user_id,tags.tag_id');
  //$query->select('*');

  $query->from($db->quoteName('#__contact_details').'AS contacts');
  $query->join('right','#__contentitem_tag_map AS tags ON `tags`.`content_item_id` = `contacts`.`id`');
  $query->where($db->quoteName("published") ." = 1  AND `tags`.`type_id` = 2 AND `tags`.`tag_id` IN (".implode(',',$tags).") ");
  $query->group('`contacts`.`id`');
  $db->setQuery($query);
  $people = $db->loadObjectList();

  return $people;

}

Joomla 3.9.0

2

Das Modul Tags - Similar Verwendet die HAVING -Klausel, um dies zu erreichen.

$query->having('COUNT(' . $db->quoteName('tags.tag_id') . ') = ' . count($tags));

Ich bin mir aber nicht sicher, ob dies die bestmögliche Lösung ist. Dies kann sehr langsam sein, da WHERE IN Erst nach Auswahl der Zeilen alle Zeilen auswählt, die mit einem beliebigen Tag und HAVING -Filtern übereinstimmen.

3
Sharky

Ich habe mir die Zeit genommen, meine eigenen Testdaten einzurichten, und Sharky hat Recht (+1 für Sharky), eine HAVING -Klausel zu implementieren.

$tag_ids = $params->get("tags");
$db = JFactory::getDbo();
$query = $db->getQuery(true)
    ->select("id, catid, name, alias, image, email_to, published, user_id")
    ->select(" GROUP_CONCAT(tags.tag_id) AS tag_ids")
    ->from("#__contact_details AS contacts")
    ->innerJoin("#__contentitem_tag_map AS tags ON tags.content_item_id = contacts.id")
    ->where("published = 1")
    ->where("type_id = 2")
    ->where("tag_id IN (" . implode(',', $tag_ids) . ")")
    ->group("contacts.id")
    ->having("COUNT(*) = " . sizeof($tag_ids));

echo $query->dump();
$db->setQuery($query);
echo "<pre>";
var_export($db->loadObjectList());

Ausgabe:

SELECT id, catid, name, alias, image, email_to, published, user_id, GROUP_CONCAT(tags.tag_id) AS tag_ids
FROM zyxwv_contact_details AS contacts
INNER JOIN zyxwv_contentitem_tag_map AS tags ON tags.content_item_id = contacts.id
WHERE published = 1 AND type_id = 2 AND tag_id IN (9,10)
GROUP BY contacts.id
HAVING COUNT(*) = 2
array (
  0 => 
  stdClass::__set_state(array(
     'id' => '12',
     'catid' => '21',
     'name' => 'Sharky',
     'alias' => 'sharky',
     'image' => 'images/sharky.jpg',
     'email_to' => '',
     'published' => '1',
     'user_id' => '0',
     'tag_ids' => '9,10',
  )),
  1 => 
  stdClass::__set_state(array(
     'id' => '82',
     'catid' => '21',
     'name' => 'mickmackusa',
     'alias' => 'mickmackusa',
     'image' => '',
     'email_to' => '',
     'published' => '1',
     'user_id' => '0',
     'tag_ids' => '9,10',
  )),
)
  • Verwenden Sie GROUP_CONCAT() in der SELECT -Klausel, um alle tag_ids in der Ergebnismenge anzuzeigen.
  • Ich bevorzuge die Logik, INNER JOIN gegenüber RIGHT JOIN zu verwenden, aber ich weiß nicht, wie sie in Bezug auf die Leistung verglichen werden.
  • Die HAVING -Klausel kann COUNT(*) verwenden, um dasselbe Ergebnis zu erzielen wie die Eingabe der Spalte tag_id.

Durch Ändern der Zahl nach COUNT() wird festgelegt, wie viele qualifizierende Tags erforderlich sind, damit ein Kontakt/Benutzer in die Ergebnismenge aufgenommen wird. Wenn Sie beispielsweise nach 3 verschiedenen Tags suchen, aber nur 2 benötigen, erhalten Sie alle Zeilen, in denen Kontakte/Benutzer über 2 von 3 qualifizierenden Tags verfügen.

1
mickmackusa