Короткая версия:Elasticsearch Nest подстановочные запрос с пробелами
Я хотел бы написать упругую поисковый запрос, используя гнездо, чтобы получить полные индексированные элементы (ContentIndexables
в моем случае, как мой пользовательский тип), которые были проиндексированы. Запрос подлежит термину query [some string] + * (т. Е. String.StartsWith(), где [некоторая строка] может содержать или не содержать пробелы.
Это отличается от CompletionSuggester
, так как мне нужно получить полный объект, а не строка предложения
То, что я пытался до сих пор:.
Когда я запрашиваю для текста без пробелов, желаемый результат будет возвращен, используя этот код Если мой поисковый термин, однако содержит пробелы. , он не возвращает ожидаемых результатов.
Вот как я искать поля:
var searchResults = _client.Search<ContentIndexable>(
body =>
body
.Index(indexName)
.Query(
query =>
query.QueryString(
qs => qs.
OnFields(f => f.Title, f => f.TextContent)
.Query(searchTerm + "*"))));
И это тест блок, который показывает, как воспроизвести проблему:
indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
{
ContentId = Guid.NewGuid(),
TextContent = "Some description",
Title = "title"
});
indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
{
ContentId = Guid.NewGuid(),
TextContent = "Some description",
Title = "title that is long"
});
indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
{
ContentId = Guid.NewGuid(),
TextContent = "Some description",
Title = "title that likes"
});
indexService.IndexUserItemsSync(testGuid, IndexType.submission, new ContentIndexable
{
ContentId = Guid.NewGuid(),
TextContent = "Some description",
Title = "titlethat"
});
var searchResult = indexService.SearchUserItems(testGuid, IndexType.submission, 10, "title");
Assert.IsNotNull(searchResult);
// this one works
Assert.AreEqual(4, searchResult.Count());
var searchResult2 = indexService.SearchUserItems(testGuid, IndexType.submission, 10, "title that");
Assert.IsNotNull(searchResult2);
// this one does not!!! searchREsult2.Count() evaluates to 0
Assert.AreEqual(2, searchResult2.Count());
Как вы можете видеть, то я вхожу «титул, который», то поиск возвращается пустой, а не две строки, которые я ожидал бы вернуться.
Update: Некоторые больше информации: создать индекс по моему типу ContentIndexable:
public class ContentIndexable : IIndexable
{
public Guid ContentId { get; set; }
public string Title { get; set; }
public string TextContent { get; set; }
}
С помощью этого кода:
_client.CreateIndex(
indexName,
descriptor =>
descriptor.AddMapping<ContentIndexable>(
m => m.Properties(
p => p.Completion(s => s
.Name(n => n.Title)
.IndexAnalyzer("standard")
.SearchAnalyzer("standard")
.MaxInputLength(30)
.Payloads()
.PreserveSeparators()
.PreservePositionIncrements())
.Completion(s => s.Name(n => n.TextContent)
.IndexAnalyzer("standard")
.SearchAnalyzer("standard")
.MaxInputLength(50)
.Payloads()
.PreserveSeparators()
.PreservePositionIncrements())
)));
Я даже пытался избежать пробелов и когда Я индексирую или когда я запрашиваю string.Replace(" ", @"\ ")
, но это не помогло.
Изменение типа поиска на джокера не помогло:
var searchResults = _client.Search<ContentIndexable>(
body =>
body
.Index(indexName)
.Query(
query => query.Wildcard(qd => qd.OnField(f => f.Title).Value(searchTerm + "*"))));
Кто-нибудь знает, что я делаю неправильно?
Обратите внимание: моя версия CompletionSuggester
работает с пробелами, но, к сожалению, только возвращает строки. Мне нужно получить полный товар, чтобы получить ContentId
. МОЯ реализация CompletionSuggester:
public IEnumerable<string> GetAutoCompleteSuggestions(Guid userId, IndexType indexType, int size, string searchTerm)
{
string indexName = getIndexName(indexType, userId);
var result = _client.Search<ContentIndexable>(
body => body.Index(indexName)
.SuggestCompletion("content-suggest" + Guid.NewGuid(),
descriptor => descriptor
.OnField(t => t.Title)
.Text(searchTerm)
.Size(size)));
if (result.Suggest == null)
{
return new List<string>();
}
return (from suggest in result.Suggest
from value in suggest.Value
from options in value.Options
select options.Text).Take(size);
}
Я знаю, что может принять предложения, получить полную отдачу (что приведет к двум пунктам я ожидал), а затем сделать полный термин матч, используя свой первый метод, но что требует 2 отдельных вызова в ElasticSearch (один для полного предложения и второй для запроса термина), но в идеале я хотел бы сделать это без кругового путешествия, если это возможно.
Большое спасибо заранее,
Вы пытаетесь внедрить [завершение семинара] (http://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html), или, скорее, ваше сопоставление - это что-то вроде «возможно это будет работать »? – Rob
Привет @Rob. Я уже сделал завершающего экзаменатора, но это возвращает мне список строк. Этот список является правильным и содержит элементы с пробелами правильно. То, что я хотел бы сделать, - это сделать то же самое с запросом, который дает мне тот же результат (с пробелами), но вместо строк в качестве предложений мне нужно получить весь проиндексированный объект (ContentIndexable в моем случае). Я полный новичок в ElasticSearch, как вы, возможно, догадались, поэтому любое предложение будет оценено по достоинству. – kha