2016-04-02 17 views
0

C# elasticsearch.net kütüphanesi kullanıyorum ve belirtilen filtreye uyan nesneler için sorgu çalışıyorum.Dizeler dizisi dizeleri dizisi tarafından sorgu dizisi sorgulama

Sorgunun, nesnenin Adlar koleksiyonunda filtreden gelen giriş adlarından en az birinin bulunduğu nesneleri döndürmesini istiyorum.

Sorun şu ki, bu sorgu ile sonuç olarak her zaman 0 isabet aldığımda bile, veritabanında belirtilen filtre ile eşleşen veri var olduğunu ve sorgumda neyin yanlış olduğunu öğrenmeyi çok isterim ...

modeli:

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

filtreleme nesnesi:

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

veri sorgulamak için bir yöntem:

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(); 
} 

Ben de sorguyu aşağıdaki denedi, ancak beklenen bir sonuç vermemiştir ne: BENİM İÇİN ÇALIŞTI

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)); 

ÇÖZÜM: Ben Sławomir Rosiek's answer biraz kodunu yükseltilmiş

Aslında ElasticSearch.net 1.7.1 kullanarak derlemek ve tip güvenli (dize ile alan adına başvuru yok) ve benim senaryo için bir çekicilik gibi çalıştı aşağıdaki uzantısı yöntemi ile sona erdi:

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; 
} 

ve kullanımı:

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

Ayrıca 'Şartları kullanabilirsiniz()' sorgu/filtre edildiği de terimlerin dizi geçen Bunu başarmak için En az biri eşleşmeli. –

+0

@RussCam Evet, yukarıda anlattığım gibi, 0 isabeti de denedim. –

+0

NEST'in hangi sürümünü kullanıyorsunuz ve hangi Elasticsearch sürümüne karşı çalışıyorsunuz? –

cevap

2

Ben senin sorunun sorgulamak için tüm dizi geçirmeye çalışır olduğunu düşünüyorum. Bunun yerine, bunu VEYA ifadesi olarak ele almalısınız.

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

Ve C# kodu olduğunu başarmak için bu:

Aşağıda kullanmalısınız çiğ sorgusu olur. Önce tanımladık yardımcı işlevi:

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; 
} 

Ve şimdi sorgusu:

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

Cevabınız için teşekkürler, çok yardımcı oldu. Kullandığım elasticsearch.net sürümünde 'QueryContainerDescriptor' ve 'Field' türlerini kullanmadığım için kodunuzu biraz değiştirdim (v. 1.7.1). –