10
votes

Récupérer des documents contenant uniquement des balises autorisées (exactement égale)

Pour chaque demande de recherche, j'ai autorisé la liste des tags. Par exemple, xxx pré>

et je souhaite récupérer des documents avec toutes les balises de cette liste. Je veux récupérer: p> xxx pré>

et exclure p> xxx pré>

car la liste ne contient pas windows code > Tag. P>

Il y a un exemple pour égaux exactement dans la documentation élastiquesarch: p>

HttTPS://www.elastic.co/guide/fr/elasticsearch/Guide/Currrent/_finding_multiple_extact_values.html P>

Tout d'abord, nous incluons un champ qui maintient Le nombre de tags: p> xxx pré>

Deuxièmement, nous récupérons avec lesquels TAG_COUNT P>

GET /my_index/my_type/_search
{
    "query": {
        "filtered" : {
            "filter" : {
                 "bool" : {
                    "must" : [
                        { "term" : { "tags" : "search" } }, 
                        { "term" : { "tags" : "open_source" } }, 
                        { "term" : { "tag_count" : 2 } } 
                    ]
                }
            }
        }
    }
}


7 commentaires

Vous ne pouvez pas calculer le nombre de balises au moment de l'indexation, cela peut normalement être obtenu avec un script simple. Non?


@Sergey Shuvalov Pouvez-vous décrire ce qui ne fonctionne pas pour vous dans la réponse acceptée.


Je crois que devrait être une solution plus agile. GetInting "minimum_should_match" ou "Nombre de balises" de manière dynamique, peut être. À cause de "Tag_Count", JSON sera énorme.


J'ai répondu à une question exacte ici , cela pourrait prendre quelques secondes bien que


@ Chintanshah25, merci pour le script. Je pense que si nous pouvons rejoindre ces deux réponses différentes, nous pouvons obtenir une excellente solution.


Je ne suis pas sûr que deux réponses dont vous parlez, le seul problème avec le script est la performance, même si j'ai ajouté des termes filtres pour exclure des documents non-questionnaires pour effectuer des scripts, il pourrait être trop lent si vous avez un grand tableau, mais je vais vous donner sûrement les résultats souhaités


J'ai amélioré ce script en utilisant contenant la méthode et en supprimant toutes les autres choses.


5 Réponses :


0
votes

Pourquoi ne pas utiliser le bool avec des fenêtres ajoutées pour ne pas être clause. J'espère que c'est ce que vous cherchez.


0 commentaires

1
votes

Alors j'avoue que cela n'est pas une excellente solution, mais peut-être qu'elle inspirera d'autres meilleures solutions?

donnée des parties des archives que vous recherchez ressemblent à ce que vous avez dans votre message avec les champs Tag_Count: xxx

ou xxx

et vous avez une requête comme: xxx

alors puis Vous pourriez générer de manière programmable une requête comme: xxx

Le nombre de requêtes de bool imbriquées correspondra à la requête de numéro des étiquettes de requête (pas géniale pour un certain nombre de raisons - mais avec des requêtes plus petites / Indices plus petits, peut peut-être sortir avec cela?). Fondamentalement, chaque clause gérera chaque cas possible de tag_count et de minimum_should_match sera Tag_Count + 1 (donc Match Tag_Count et le nombre approprié de balises - TAG_COUNT MONTERE).


0 commentaires

0
votes

@Sergey Shuvalov, une autre façon de s'en sortir sans utiliser de script consiste à créer un autre champ dont la valeur contient toutes les balises triées séparées par une virgule (par exemple, ou si vous pouvez choisir le séparateur vous convient).

Par exemple, si vous avez un document comme celui-ci: p>

{
  "query": {
    "term": {
      "alltags": "freeware,linux,open_source,search"
    }
  }
}


6 commentaires

En raison de la partie exclusive?


{"Tags": ["Recherche", "Freeware"]}. Vous ne pouvez pas trouver ce doc avec votre solution


Pouvez-vous élaborer pourquoi pas? Vous souciez-vous également de la partie exclusive ou non? Il n'est pas clair si votre besoin est exactement comme dans la question ou diffère d'une manière ou d'une autre. S'il vous plaît, aidez-nous à vous aider.


Je veux quelque chose comme: est toutes les valeurs dans les balises ("Recherche", "Freeware") Localisez dans Param Array ("Recherche", "Open_Source", "Freeware", "Linux").


Vous avez donc besoin d'une recherche partielle. Vous devez simplement savoir si les tags de la requête sont Tous inclus dans les balises dans le document, qui est différente de la question initiale IMHO (qui indique "exactement égale"). Pouvez-vous confirmer?


Oui, je confirme. Mais en question: " et je veux récupérer des documents avec toutes les balises de cette liste. Je veux récupérer: {" Tags ": [" Recherche "," Freeware "]} et excluez {" Tags ": [" Recherche "," Windows "]} Parce que la liste ne contient pas" Windows "Tag ".



1
votes

Si la taille de l'index est de taille moyenne et la cardinalité des balises est plutôt faible, je voudrais simplement utiliser termes d'agrégation pour obtenir des balises distinctes et créer doit et ne doit pas Filtres Pour filtrer les documents contenant des étiquettes que vous n'avez pas "Autoriser". Il existe de nombreuses façons de mettre en cache la liste de toutes les balises dans une base de données en mémoire comme Redis, voici quelques-uns qui me sont venus à mon esprit:

  1. Demandez un temps à vivre de quelques minutes ou quelques heures, réinitier la liste si le cache a expiré
  2. avoir un processus de fond rafraîchissant la liste à intervalles réguliers
  3. Mettez à jour la liste lorsque de nouveaux documents sont insérés, les suppressions DOC doivent être traitées aussi bien

    Une méthode plus performante et 100% précise pourrait ressembler à ceci:

    1. Quertiez tous les documents qui ont les balises demandées mais excluent les documents avec d'autres balises connues (comme avec la première solution)
    2. passer par la liste des documents retournés
    3. Si un document contient une balise qui n'est pas "autorisée", cela signifie qu'il n'était pas dans le cache de balises connu et qu'il doit donc être ajouté là-bas, exclure ce doc de l'ensemble de résultats
    4. Tags à Redis pourrait avoir un TTL de par exemple un jour ou une semaine, de cette façon, les anciennes balises sont automatiquement élagues et que vous obtenez des requêtes ES plus simples

      De cette façon, vous n'avez pas besoin d'un processus de sauvegarde pour maintenir la liste des balises ou utiliser les termes éventuellement lourds Agrégation car il frappe tous les documents et obtenez toujours le bon ensemble de résultats et des requêtes relativement performantes. .

      Cela ne fonctionnerait pas si des agrégations ultérieures sont utilisées comme ES pourraient renvoyer de faux documents éliminés du côté du client. Cependant, cela pourrait être détecté en ajoutant une agrégation de termes et confirmez qu'il n'a pas de balises inattendues. Si cela doit être ajouté au cache de balises, ajouté au filtre MUST_NOT et la requête doit être ré-exécuté. Ce n'est pas idéal si de nouvelles balises sont créées fréquemment.


0 commentaires

0
votes

Comme je l'ai mentionné tôt, je combine deux belles réponses. Et c'est ce que j'ai: xxx

condition de script fonctionne avec des cas non-triviaux et d'autres conditions sont là pour envisager de simples cas.


0 commentaires