我想只返回名字以" pizza"开头的文件。这就是我所做的:
{
"query": {
"filtered": {
"filter": {
"prefix": {
"name": "pizza"
}
}
}
}
}
但我已经收到了这三份文件:
{
"name": "Viana Pizza",
"city": "Mashhad",
"address": "Vakil abad",
"foods": ["Pizza"],
"salad": true,
"rate": 5.0
}
{
"name": "Pizza Pizza",
"city": "Mashhad",
"address": "Bahar st",
"foods": ["Pizza"],
"salad": true,
"rate": 8.5
}
{
"name": "Reza Pizza",
"city": "Tehran",
"address": "Vali Asr",
"foods": ["Pizza"],
"salad": true,
"rate": 7.5
}
正如你所看到的,只有其中一个人有#14;披萨"在名称字段的开头。 怎么了?
答案 0 :(得分:2)
可能最简单的解释是,你没有提供实际的映射,就是你有一个" name" field as" string"和"分析" (默认)。这意味着" Reza Pizza"将转变为" reza"和#34;披萨"术语
您的过滤器将与术语匹配,而不是与整个字段匹配。因为ES在使用标准映射时分析字段和表单术语。
你需要改变你的名字"字段到" not_analyzed"或添加另一个字段来镜像" name"但是这个镜像领域是" not_analyzed"。此外,对于文字"披萨" (小写)在这种情况下工作,你需要创建一个自定义分析器。
下面是镜像字段的解决方案:
PUT /pizza
{
"settings": {
"analysis": {
"analyzer": {
"my_keyword_lowercase_analyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"restaurant": {
"properties": {
"name": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"analyzer": "my_keyword_lowercase_analyzer"
}
}
}
}
}
}
}
在搜索中你需要使用镜像字段:
GET /pizza/restaurant/_search
{
"query": {
"filtered": {
"filter": {
"prefix": {
"name.raw": "pizza"
}
}
}
}
}
答案 1 :(得分:2)
这完全是关于Elasticsearch analyzers的。让我们阅读prefix
过滤器上的documentation:
Filters documents that have fields containing terms with a specified prefix (not analyzed).
在这里,我们可以看到此过滤器与字词匹配,而不是整个字段值。索引文档时,ES会使用分析器将字段值拆分为术语。默认分析器按空格分割值并将部件转换为lowercse。因此,所有三个结果都在名称字段中包含术语披萨,而pizza
字词与pizza
前缀完全匹配。如果您希望按原样匹配字段值,我建议您将名称字段映射为not_analyzed