2016-04-02 15 views
0

Ich benutze elasticsearch.net-Bibliothek in C# und ich versuche, für Objekte mit angegebenen Filter abzufragen.Abfrage Array von Zeichenfolgen nach Array von Zeichenfolgen in elasticsearch.net

Ich möchte, dass die Abfrage Objekte zurückgibt, bei denen mindestens einer der Eingabe-Namen aus dem Filter in der Names-Auflistung des Objekts vorhanden ist.

Das Problem ist, dass ich immer 0 Treffer als Ergebnis mit dieser Abfrage bekomme, auch wenn ich bin sicher, dass Daten mit angegebenen Filter in der Datenbank vorhanden sind und ich würde gerne herausfinden, was mit meiner Abfrage falsch ist ...

Das Modell:

public class A 
{ 
    public int AId { get; set; } 
    public IEnumerable<string> Names { get; set; } 
} 

Die Objektfilterungs:

public class Filter 
{ 
    public IEnumerable<string> NamesToSearch { get; set; } 
} 

Das Verfahren zum Abfragen von Daten:

public async Task<IEnumerable<A>> GetFilteredData(Filter filter) 
{ 
    var query = await _elasticClient.SearchAsync<A>(x => x.Query(q => q.Terms(a => a.Names, filter.NamesToSearch)) 
                  .Fields(a => a.AId, a => a.Names)); 

    return query.Hits 
       .Select(x => new A 
           { 
            AId = x.Fields.FieldValues<A, int>(a => a.AId)[0] 
           }) 
       .ToList(); 
} 

Ich habe auch versucht Abfrage nach, aber es hat nicht erwartete Ergebnis liefern weder:

var query = await _elasticClient.SearchAsync<A>(x => x.Query(q => q.Nested(n => n.Filter(f => f.Terms(y => y.Names, filter.NamesToSearch)))) 
                   .Fields(a => a.AId, a => a.Names)); 

Lösung, die für mich gearbeitet:

ich ein bisschen Code aus Sławomir Rosiek's answer Upgrade um tatsächlich mit ElasticSearch.net 1.7.1 zu kompilieren und typsicher zu sein (keine Verweise auf Feldname nach Zeichenkette) und endete mit der folgenden Erweiterungsmethode, die wie ein Zauber für mein Szenario funktionierte:

public static QueryContainer MatchAnyTerm<T>(this QueryDescriptor<T> descriptor, Expression<Func<T, object>> field, object[] values) where T : class, new() 
{ 
    var queryContainer = new QueryContainer(); 

    foreach (var value in values) 
    { 
     queryContainer |= descriptor.Term(t => t.OnField(field).Value(value)); 
    } 

    return queryContainer; 
} 

und Nutzung:

var query = await _elasticClient.SearchAsync<A>(x => x.Query(q => 
                   q.Bool(b => 
                    b.Should(s => s.MatchAnyTerm(a => a.Names, filter.NamesToSearch.ToArray())) 
                     .Fields(a => a.AId, a => a.Names)); 
+0

Sie auch die 'Bedingungen()' Abfrage/Filter verwenden, könnte dies zu erreichen, vorbei an der Reihe von Bedingungen, in denen bei mindestens sollte einer übereinstimmen. –

+0

@RussCam Ja, ich habe es versucht und es gab 0 Treffer, genau wie oben beschrieben. –

+0

Welche Version von NEST verwenden Sie und welche Version von Elasticsearch verwenden Sie? –

Antwort

2

Ich denke, dass Ihr Problem ist, dass man versucht, ganze Array übergeben abzufragen. Stattdessen sollten Sie das als OR-Ausdruck behandeln.

Unten ist die rohe Abfrage, die Sie verwenden sollten:

{ 
    "query": { 
     "bool": { 
      "should": [ 
       { "term": {"names": "test" } }, 
       { "term": {"names": "xyz" } } 
      ] 
     } 
    } 
} 

Und dass der C# -Code, dass achive. Zuerst habe ich definiert Hilfsfunktion:

private static QueryContainer TermAny<T>(QueryContainerDescriptor<T> descriptor, Field field, object[] values) where T : class 
{ 
    QueryContainer q = new QueryContainer(); 
    foreach (var value in values) 
    { 
     q |= descriptor.Term(t => t.Field(field).Value(value)); 
    } 
    return q; 
} 

Und nun die Abfrage:

string[] values = new[] { "test", "xyz" }; 
client.Search<A>(x => x.Query(
    q => q.Bool(
     b => b.Should(s => TermAny(s, "names", values))))); 
+0

Danke für Ihre Antwort, es war sehr hilfreich. Ich habe Ihren Code leicht modifiziert, damit er funktioniert, da die Typen 'QueryContainerDescriptor' und 'Field' in der von mir verwendeten Version von elasticsearch.net (v. 1.7.1) nicht gefunden wurden. –

Verwandte Themen