2 votes

Faire correspondre plusieurs phrases à un champ dans Elastic Search

J'ai construit une application en C# qui recherche mes documents Elasticsearch et tout fonctionne bien en utilisant ce code.....

List<AuditLog> resultsList = Client.SearchAsync<AuditLog>(s => s
    .From(0)
    .Take(noRows)
    .Query(q => q
        .Bool(b => b
            .Must(mu => mu.MatchPhrase(mp => mp.Field("audit_Event").Query(auditEvents)),
                mu => mu.Match(ma => ma.Field(field).Query(value))
             )
          )
     )).Result.Documents.ToList();

Tout cela fonctionne bien, mais il y a un nouveau besoin de rechercher le champ audit_Event par rapport à plusieurs phrases, telles que "User Login", "Add Employee", etc.

J'ai trouvé des références à multi_match mais cela semble être plus lié à la recherche sur plusieurs champs plutôt que sur plusieurs valeurs dans un seul champ.

En suivant les discussions ci-dessous, TermQuery semble faire le travail mais ne renvoie aucune valeur. Avez-vous une idée ?

QueryContainer queryAnd = new TermQuery() { Field = "audit_Application", Value = "MyApplication" };
QueryContainer queryOr = new TermQuery() { Field = "audit_Event", Value = "Employee Inserted" };
queryOr |= new TermQuery() { Field = "audit_Event", Value = "Employee Updated" }; 
QueryContainer queryMain = queryAnd & queryOr;

resultsList = Client.SearchAsync<AuditLog>(s => s
    .From(0)
    .Take(noRows)
    .Query(q => q
        .Bool(b => b
            .Must(queryMain)
        )
    )).Result.Documents.ToList();

J'ai également vérifié les deux requêtes à l'aide de Kibana, la première renvoie des données mais pas la seconde, et je me demande maintenant s'il ne s'agit pas d'un problème avec la façon dont les données sont indexées.....

GET auditlog/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match_phrase": {
            "audit_Event": "Employee Updated"
          }
        },
        {
          "match_phrase": {
            "audit_Event": "Employee Inserted"
          }
        }
      ]
    }
  }
}

GET auditlog/_search
{
  "query" : {
    "terms": {
        "audit_Event": ["Employee Updated","Employee Inserted"]
    }
  }
}

0voto

ESCoder Points 10803

Si vous souhaitez faire correspondre plusieurs phrases à un seul champ, vous pouvez utiliser les combinaisons suivantes d'éléments bool query avec match_phrase

{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "audit_Event": "User Login"
          }
        },
        {
          "match_phrase": {
            "audit_Event": "Add Employee"
          }
        }
      ]
    }
  }
}

0voto

Muzaffer GALATA Points 61

Essayez ceci, s'il vous plaît :

QueryContainer queryOr = new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Inserted" };
        queryOr |= new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Updated" };
        ISearchResponse<AuditLog> resultAuditLog = Client.Search<AuditLog>(s => s
                    .RequestConfiguration(r => r.DisableDirectStreaming())
                    .From(0)
                    .Size(100)
                    .Query(q2 => q2
                        .Bool(b => b
                        .Should(queryOr))
                    )
        );

0voto

Sai Gummaluri Points 1026

En se basant sur votre déclaration selon laquelle le OR fonctionne comme prévu, vous trouverez ci-dessous une façon de construire la requête en utilisant NEST . Vous pouvez apporter des modifications spécifiques si nécessaire.

Ce bout de code est responsable du déclenchement de l'appel de recherche.

var searchDescriptor = new SearchDescriptor<AuditLog>()
    .Query(q => Blah(auditEventsList))
    .From(0)
    .Take(noRows);
    // other methods you want to chain here

var response = Client.searchAsync<AuditLog>(searchDescriptor);

La requête de recherche est générée ici. Remarquez l'utilisation de SHOULD et l'appel à une autre méthode qui est responsable de la génération dynamique de l'élément match_phrase des requêtes.

private static QueryContainer Blah(List<string> auditEventsList)
{
    return new QueryContainerDescriptor<AuditLog>().Bool(
        b => b.Should(
            InnerBlah(auditEventsList)
        )
    );
}

Cette méthode génère un tableau de match_phrase qui sont transmises à should dans l'extrait ci-dessus. Ceux-ci sont générés en itérant sur tous les événements d'audit qui sont reçus.

private static QueryContainer[] InnerBlah(List<string> auditEventsList)
{
    QueryContainer orQuery = null;
    List<QueryContainer> queryContainerList = new List<QueryContainer>();
    foreach(var item in auditEventsList)
    {
        orQuery = new MatchPhraseQuery { Field = "audit_Event", Query = item };
        queryContainerList.Add(orQuery);
    }
    return queryContainerList.ToArray();
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X