Я использую библиотеку elasticsearch.net на C#, и я пытаюсь запросить объекты, соответствующие указанному фильтру.Запрос массива строк по массиву строк в elasticsearch.net
Я хочу, чтобы запрос возвращал объекты, в которых по крайней мере одно из входных имен из фильтра существует в коллекции имен объектов.
Проблема в том, что я всегда получаю 0 ударов в результате этого запроса, даже если я уверен, что данные, соответствующие указанному фильтру, существуют в базе данных, и я хотел бы узнать, что не так с моим запросом ...
модель:
public class A
{
public int AId { get; set; }
public IEnumerable<string> Names { get; set; }
}
фильтрация объекта:
public class Filter
{
public IEnumerable<string> NamesToSearch { get; set; }
}
Способ запроса данных:
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();
}
Я также пробовал следующий запрос, но не дали ожидаемого результата, ни:
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));
РЕШЕНИЕ КОТОРОЙ РАБОТАЛ ДЛЯ МЕНЯ:
Я модернизировал немного кода из Sławomir Rosiek's answer фактически скомпилировать с помощью ElasticSearch.net 1.7.1 и быть безопасным по типу (без ссылок на имя поля по строкам), и в итоге появился следующий метод расширения, который работал как прелесть для моего сценария:
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;
}
и использование:
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));
Вы также можете использовать 'Термины()' запрос/фильтр для достижения этой цели, передавая массив терминов, в которых в по крайней мере, один должен соответствовать. –
@ RussCam Да, я пробовал, и он дал 0 ударов, как я описал выше. –
какую версию NEST вы используете и с какой версией Elasticsearch вы работаете? –