我的弹性数据设置有不同的字段:类别,子类别,工具和情绪.我的目标是为所有传递给它的关键字提供完全匹配的结果,并且仅返回与所有关键字匹配的结果.到目前为止,这似乎有效,直到我使用由空格分隔的多个单词组成的关键字,如下所示:
"query": {
"bool": {
"must": [
{
"match": {
"categories": "Electronic"
}
},
{
"match": {
"categories": "Pop"
}
},
{
"match": {
"instruments": "Female Vocal"
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
我在ES中的数据包含以下类型的数据:
[name] => Some Data Name
[categories] => Electronic,Pop
[subcategories] => 1970s,Alternative,Experimental,Retro
[instruments] => Electronic Drums,Male Vocal,Synth
[moods] => Fun,Futuristic,Pulsing,Quirky,Rhythmic
Run Code Online (Sandbox Code Playgroud)
因此,它与乐器领域的"声乐"部分相匹配,但不会与"女声"完全匹配.
这可能是由ES过滤器解决的吗?
编辑:为了解释其他字符,我稍微扩展了示例数据集:
[categories]=>R&B,Dance/House
[instruments] => Electronic Drums,Male Vocal,Synth
[moods] => Fun,Futuristic,Pulsing,Quirky,Rhythmic
Run Code Online (Sandbox Code Playgroud)
因此,可能会使用&符号,斜杠和空格.逗号会将单独的术语分开.
解决了 我最后更多地关注分析器,并意识到我可能需要创建一个自定义的分析器来解释我的关键字的边界.
myesurl/tracks/_settings
{
"index": {
"analysis": {
"tokenizer": {
"comma": {
"type": "pattern",
"pattern": ","
}
},
"analyzer": {
"tracks_analyzer": {
"type": "custom",
"tokenizer": "comma",
"filter": [
"trim",
"lowercase"
]
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我设置了一个映射:
{
"track": {
"properties": {
"categories": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"subcategories": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"instruments": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"moods": {
"type": "string",
"analyzer": "tracks_analyzer"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后将内容推送到弹性搜索中.似乎按预期工作.它现在考虑关键字中的任何字符,只要该关键字与由分隔逗号创建的标记匹配即可.
使用match
查询意味着您输入的任何字符串都由标准分析器进行分析,因此会分隔在空格和小写字母上.所以你可以看到,只要你在每个字段中匹配一个单词就可以了.但是,只要你搜索的内容包含空格,就会产生乐趣.
发生的事情是,在索引时,Female Vocal
将分为两个标记female
并将vocal
其索引到instruments
字段中.这同样适用于Male Vocal
被索引视为两个标记male
和vocal
.因此也会匹配字段Male Vocal
.然后,当你在match
荷兰国际集团上Female Vocal
,什么情况是,搜索词进行分拆,小写字母以及进入female
和vocal
和术语vocal
将匹配与这两个文件Male Vocal
和Female Vocal
.
如果您想要完全匹配,则需要两件事:1.声明您需要与not_analyzed
映射完全匹配的字符串字段2.使用不分析搜索项的term
查询(或term
过滤器).
第一点很容易用这样的映射:
curl -XPUT localhost:9200/my_index -d '{
"mappings": {
"my_type": {
"properties": {
"categories": {
"type": "string",
"index": "not_analyzed"
},
"subcategories": {
"type": "string",
"index": "not_analyzed"
},
"instruments": {
"type": "string",
"index": "not_analyzed"
},
"moods": {
"type": "string",
"index": "not_analyzed"
},
...
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
使用这样的映射,Female Vocal
将不会被分析(即没有被索引为female
和vocal
),而是逐字索引为Female Vocal
.
然后,您可以使用如下查询查询确切的字段值:
curl -XPOST localhost:9200/my_index/my_type/_search -d '{
"query": {
"bool": {
"must": [
{
"term": {
"categories": "Electronic"
}
},
{
"term": {
"categories": "Pop"
}
},
{
"term": {
"instruments": "Female Vocal"
}
}
]
}
}
}'
Run Code Online (Sandbox Code Playgroud)
我最终更多地研究了分析器,并意识到我可能需要创建一个自定义的分析器来解释我的关键字的边界。
myesurl/tracks/_settings
{
"index": {
"analysis": {
"tokenizer": {
"comma": {
"type": "pattern",
"pattern": ","
}
},
"analyzer": {
"tracks_analyzer": {
"type": "custom",
"tokenizer": "comma",
"filter": [
"trim",
"lowercase"
]
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我设置了一个映射:
{
"track": {
"properties": {
"categories": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"subcategories": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"instruments": {
"type": "string",
"analyzer": "tracks_analyzer"
},
"moods": {
"type": "string",
"analyzer": "tracks_analyzer"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后将内容推送到elasticsearch中。似乎按预期工作。它现在考虑关键字中的任何字符,只要关键字与由分隔逗号创建的标记匹配即可。
一个不错的解决方案是使用match
and minimum_should_match
,提供您想要匹配的单词的百分比。它可以是 100%,并且将返回至少包含给定文本的结果;
重要的是,这种方法不考虑单词的顺序。
"query":{
"bool":{
"should":[
{
"match":{
"my_text":{
"query":"I want to buy a new new car",
"minimum_should_match":"90%"
}
}
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8664 次 |
最近记录: |