Я пытаюсь создать компонент, который предлагает подсказки автозаполнения для пользователей и групп. Я используюasticsearch 6.5.3. Я создал индекс, который содержит поля, которые я хочу найти, и 3 дополнительных поля для фильтрации (isGroup, isUser, organizationId). В некоторых случаях я хочу использовать этот компонент для поиска всех пользователей и групп, иногда просто пользователей или просто групп или просто пользователей, принадлежащих к определенной организации. Я планировал предоставить фильтр вместе с условиями поиска в зависимости от конкретного варианта использования. Я использую гнездо для поиска, но не могу понять, как это сделать. Возможно ли это сделать, и если да, то как? Я иду по неверному пути для этого? Я в основном следовал этому руководству для создания анализатора и прочего. Я могу опубликовать свой индекс, если это поможет, но он довольно длинный.
Вот поиск с двумя из возвращенных предметов.
return client.Search<UserGroupDocument>(s => s
.Query(q=>q
.QueryString(qs=>qs.Query("adm"))
)
);
{
"_index": "users_and_groups_autocomplete_index",
"_type": "usergroupdocument",
"_id": "c54956ab-c50e-481c-b093-f9855cc74480",
"_score": 2.2962174,
"_source": {
"id": "c54956ab-c50e-481c-b093-f9855cc74480",
"isUser": true,
"isGroup": false,
"name": "admin",
"email": "admin@snapshotdesign.com",
"organizationId": 2
}
},
{
"_index": "users_and_groups_autocomplete_index",
"_type": "usergroupdocument",
"_id": "80f98d24-39e3-475d-9cb6-8f16ca472525",
"_score": 0.8630463,
"_source": {
"id": "80f98d24-39e3-475d-9cb6-8f16ca472525",
"isUser": false,
"isGroup": true,
"name": "new Group",
"users": [
{
"name": "Test User 1",
"email": "test@example.com"
},
{
"name": "admin",
"email": "admin@snapshotdesign.com"
}
],
"organizationId": 0
}
},
Таким образом, в зависимости от того, где я использую этот компонент, я могу захотеть, чтобы все они возвращались, только пользователь, только группа или просто пользователь в организации 2.
Вот мой класс UserGroupDocument
public class UserGroupDocument
{
public string Id { get; set; }
public bool IsUser { get; set; }
public bool IsGroup { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public List<User> Users { get; set; }
public long OrganizationId { get; set; }
}
И пользовательский класс
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}
Основываясь на ответе Russ Cam ниже, я изменил утверждение Must, как показано ниже Это дает мне фильтрацию, которую я хотел, но не функциональность typeahead. Мне все еще нужно набрать слово целиком, прежде чем я начну получать совпадения.
.Must(mu => mu
.QueryString(mmp => mmp
.Query(searchTerms)
.Fields(f => f
.Field(ff => ff.Name)
.Field(ff => ff.Users.Suffix("name"))
)
)
)
Вот индекс, который я использую.
{
"users_and_groups_autocomplete_index": {
"aliases": {},
"mappings": {
"usergroupdocument": {
"properties": {
"email": {
"type": "text",
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "autocomplete"
}
}
},
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"isGroup": {
"type": "boolean"
},
"isUser": {
"type": "boolean"
},
"name": {
"type": "text",
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "autocomplete"
}
}
},
"organizationId": {
"type": "long"
},
"users": {
"properties": {
"email": {
"type": "text",
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "autocomplete"
}
}
},
"name": {
"type": "text",
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "autocomplete"
}
}
}
}
}
}
}
},
"settings": {
"index": {
"number_of_shards": "5",
"provided_name": "users_and_groups_autocomplete_index",
"creation_date": "1548363729311",
"analysis": {
"analyzer": {
"autocomplete": {
"filter": [
"lowercase"
],
"type": "custom",
"tokenizer": "autocomplete"
}
},
"tokenizer": {
"autocomplete": {
"token_chars": [
"digit",
"letter"
],
"min_gram": "1",
"type": "edge_ngram",
"max_gram": "20"
}
}
},
"number_of_replicas": "1",
"uuid": "Vxv-y58qQTG8Uh76Doi_dA",
"version": {
"created": "6050399"
}
}
}
}
}