我需要提供靈活的全名搜索,并滿足以下要求:
- 可以按名稱搜索
- 可以按姓氏搜索
- 可以按姓名和姓氏搜索,反之亦然
- 可以按部分姓名或姓氏搜索
作為輸入,我只有字串,所以名字或姓氏都沒有關系。所以我決定使用 edge ngram tokenizer 并支持搜索變音符號。
我有以下索引:
DELETE test.full.name
PUT test.full.name
{
"settings": {
"index": {
"number_of_shards": "1",
"analysis": {
"filter": {
"edge_ngram_tokenizer": {
"token_chars": [
"letter",
"digit"
],
"min_gram": "3",
"type": "edge_ngram",
"max_gram": "3"
}
},
"analyzer": {
"edge_ngram_multi_lang": {
"filter": [
"lowercase",
"german_normalization",
"edge_ngram_tokenizer"
],
"tokenizer": "standard"
}
}
},
"number_of_replicas": "1"
}
},
"mappings": {
"properties": {
"fullName": {
"type": "text",
"analyzer": "edge_ngram_multi_lang"
}
}
}
}
并創建一些包含資料的檔案:
POST test.full.name/_doc
{
"fullName": "Ruslan test"
}
POST test.full.name/_doc
{
"fullName": "Russell test"
}
POST test.full.name/_doc
{
"fullName": "Rust test"
}
查詢搜索是:
GET test.full.name/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"fullName": {
"query": "ruslan",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
它回傳所有三個檔案,但它必須只回傳存在ruslan值的檔案。
下一個搜索查詢:
GET test.full.name/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"fullName": {
"query": "ruslan test",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
它還回傳三個檔案,但預計只有帶有“ruslan test”的檔案。此外,應該可以按查詢搜索的任何順序按全名查找用戶,當然部分搜索也應該作業,就像“rus”搜索應該回傳所有具有fullName該值的檔案一樣。
此外,使用“Ruslan test”查詢應該回傳帶有“test ruslan”、“ruslan test”的檔案,查詢“test ruslan”也是如此。
那么應該如何配置索引來接受上述要求呢?
uj5u.com熱心網友回復:
您正在使用edge_ngram_tokenizer,根據您的索引設定,它將生成最小長度為 3 和最大長度為 3 的 N-gram。您可以使用Analyze API對此進行測驗:
GET /_analyze
{
"analyzer" : "edge_ngram_multi_lang",
"text" : "Ruslan test"
}
生成的令牌是:
{
"tokens": [
{
"token": "rus",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "tes",
"start_offset": 7,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 1
}
]
}
由于這不是您的要求,您應該使用Shingle令牌過濾器而不是 Edge-ngram
添加具有索引映射、搜索查詢和搜索結果的作業示例
索引映射:
{
"settings": {
"index": {
"number_of_shards": "1",
"analysis": {
"filter": {
"my_shingle_filter": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 3
}
},
"analyzer": {
"edge_ngram_multi_lang": {
"filter": [
"lowercase",
"german_normalization",
"my_shingle_filter"
],
"tokenizer": "standard"
}
}
},
"number_of_replicas": "1"
}
},
"mappings": {
"properties": {
"fullName": {
"type": "text",
"analyzer": "edge_ngram_multi_lang"
}
}
}
}
現在生成的令牌將是
{
"tokens": [
{
"token": "ruslan",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "ruslan test",
"start_offset": 0,
"end_offset": 11,
"type": "shingle",
"position": 0,
"positionLength": 2
},
{
"token": "test",
"start_offset": 7,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 1
}
]
}
搜索介面:
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"fullName": {
"query": "test Ruslan",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
搜索結果:
"hits": [
{
"_index": "my-idx",
"_id": "4",
"_score": 0.9150312,
"_source": {
"fullName": "test Ruslan"
}
},
{
"_index": "my-idx",
"_id": "1",
"_score": 0.88840073,
"_source": {
"fullName": "Ruslan test"
}
}
]
更新1:
如果部分搜索也是您的要求,那么您應該選擇Search-as-you 欄位型別
但是您也可以使用上面答案中定義的相同索引映射設定(因為我們已經在使用帶狀皰疹)。但是您需要將搜索查詢修改為:
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"multi_match": {
"query": "rusl",
"type": "bool_prefix",
"fields": [
"fullName",
"fullName._2gram",
"fullName._3gram"
],
"operator": "AND"
}
}
]
}
}
]
}
}
}
上述索引映射和設定可用于實作問題中指出的所有測驗場景。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/477664.html
上一篇:在可滾動視窗中使用tkinter制作可變寬度的文本小部件
下一篇:Kibana搜索偏好
