2017-03-02 1 views
0

J'utilise Microsoft SQL Server Management Studio et ElasticSearch 2.3.4 avec ElasticSearch-jdbc-2.3.4.1, et j'ai lié ES avec mon serveur mssql. Tout fonctionne bien, mais quand je fais une requête en utilisant NEST sur mon programme MVC, le résultat est vide. Quand je mets une chaîne vide dans mon attribut search, j'obtiens les éléments, mais quand j'essaie de le remplir avec un filtre, j'obtiens un résultat vide. Quelqu'un peut m'aider s'il vous plaît? Merci d'avance.La requête Elasticsearch avec NEST ne fonctionne pas

C#:

const string ESServer = "http://localhost:9200"; 
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer)); 
settings.DefaultIndex("tiky"); 
settings.MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq")); 
ElasticClient client = new ElasticClient(settings); 

var response = client.Search<DAL.Faq>(s => s.Query(q => q.Term(x => x.Question, search))); 

var result = response.Documents.ToList(); 

DAL:DAL

Postman:PostMan

PS: i suivi this guide pour créer

EDIT:

cartographie Indice Index Mapping

+0

Pouvez-vous partager le mappage d'index? 'http: // localhost: 9200/tiky/_mapping' – Rob

+0

@Rob Bien sûr, j'ai mis à jour la question –

+0

Le champ' Question' est analysé et 'terms query' fonctionne avec les champs' not_analyzed'. Vous pouvez en lire plus à ce sujet [ici] (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html). – Rob

Répondre

2

Il y a deux ou trois choses que je peux voir qui peut aider ici:

  1. Par défaut, les cas de chameau NEST noms de propriété POCO lors de la sérialisation les dans le cadre de la requête JSON dans la demande, alors x => x.Question va sérialiser à "question". En regardant votre mapping cependant, les noms de champs dans Elasticsearch sont en Pascal, donc ce que le client fait ne correspondra pas à ce qui est dans Elasticsearch.

Vous pouvez modifier NEST sérialise les noms de propriétés POCO en utilisant .DefaultFieldNameInferrer(Func<string, string>) sur ConnectionSettings

const string ESServer = "http://localhost:9200"; 
ConnectionSettings settings = new ConnectionSettings(new Uri(ESServer)) 
    .DefaultIndex("tiky"); 
    .MapDefaultTypeNames(map => map.Add(typeof(DAL.Faq), "faq")) 
    // pass POCO property names through verbatim 
    .DefaultFieldNameInferrer(s => s); 

ElasticClient client = new ElasticClient(settings); 
  1. Comme mentionné Rob dans les commentaires, a term queryn'Analysons pas l'entrée de requête. Lors de l'exécution d'une requête à terme sur un champ analysé à l'heure de l'index, afin d'obtenir des correspondances, le texte de la requête que vous passez à la requête à terme doit prendre en compte l'analyse appliquée au moment de l'index. Par exemple,

    • Question est analysé avec the Standard Analyzer
    • Une valeur Question de "What's the Question?" sera analysé et indexé sous forme de jetons "what's", "the" et "question"
    • Une requête à long terme aurait besoin d'avoir une entrée de requête de "what's", "the" ou "question" être un match

Une requête de correspondance, contrairement à une requête de terme, analyse l'entrée de requête, de sorte que la sortie de l'analyse de recherche sera utilisée pour trouver des correspondances. En conjonction avec le cas Pascal mis en évidence en 1., vous devriez maintenant obtenir les documents retournés.Vous pouvez également avoir le meilleur des deux mondes dans Elasticsearch, c'est-à-dire analyser les entrées au moment de l'indexation pour la fonctionnalité de recherche de texte intégral ainsi que l'entrée d'index sans analyse pour obtenir des correspondances exactes. Cela se fait avec multi-fields et voici un exemple de création d'une cartographie qui indexe Question propriétés à la fois comme analysées et non analysées

public class Faq 
{ 
    public string Question { get; set; } 
} 

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
var defaultIndex = "default-index"; 
var connectionSettings = new ConnectionSettings(pool) 
     .DefaultIndex(defaultIndex) 
     .DefaultFieldNameInferrer(s => s); 

var client = new ElasticClient(connectionSettings); 

if (client.IndexExists(defaultIndex).Exists) 
    client.DeleteIndex(defaultIndex); 

client.CreateIndex(defaultIndex, c => c 
    .Mappings(m => m 
     .Map<Faq>(mm => mm 
      // let NEST infer mapping from the POCO 
      .AutoMap() 
      // override any inferred mappings explicitly 
      .Properties(p => p 
       .String(s => s 
        .Name(n => n.Question) 
        .Fields(f => f 
         .String(ss => ss 
          .Name("raw") 
          .NotAnalyzed() 
         ) 
        ) 
       ) 
      ) 
     ) 
    ) 
); 

La mise en correspondance pour cela ressemble

{ 
    "mappings": { 
    "faq": { 
     "properties": { 
     "Question": { 
      "type": "string", 
      "fields": { 
      "raw": { 
       "type": "string", 
       "index": "not_analyzed" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Le champ sous "raw" sous la "Question" le champ indexera la valeur de la propriété Question sans aucune analyse, c'est-à-dire verbatim. Ce champ sous-marin peut maintenant être utilisé dans une requête à long terme pour trouver des correspondances exactes

client.Search<Faq>(s => s 
    .Query(q => q 
     .Term(f => f.Question.Suffix("raw"), "What's the Question?") 
    ) 
); 

qui trouvent les résultats obtenus pour l'exemple précédent.

+1

Merci pour les conseils! C'est en fait ce dont j'avais besoin et c'est bien décrit, merci l'homme! –