【问题标题】:Elasticsearch query for multiple terms多个术语的 Elasticsearch 查询
【发布时间】:2019-12-25 20:59:25
【问题描述】:

我正在尝试创建一个允许按名称和类型进行搜索的搜索查询。 我已经索引了这些值,我在 Elasticsearch 中的记录如下所示:

{
  _index: "assets",
  _type: "asset",
  _id: "eAOEN28BcFmQazI-nngR",
  _score: 1,
  _source: {
    name: "test.png",
    mediaType: "IMAGE",
    meta: {
      content-type: "image/png",
      width: 3348,
      height: 1890,
    },
    createdAt: "2019-12-24T10:47:15.727Z",
    updatedAt: "2019-12-24T10:47:15.727Z",
  }
}

那么,例如,我将如何创建一个查询来查找所有名称为“test”并且是图像的资产?

我尝试了 multi_mach 查询,但没有返回正确的结果:

{
  "query": {
    "multi_match" : {
      "query":      "*test* IMAGE",
      "type":       "cross_fields",
      "fields":     [ "name", "mediaType" ],
      "operator":   "and" 
    }
  }
}

上面的查询返回 0 个结果,如果我将运算符更改为“或”,它将返回所有这些 IMAGE 类型的资产。

任何建议将不胜感激。蒂亚!

编辑:添加映射 下面是映射:

{
    "assets": {
        "aliases": {},
        "mappings": {
            "properties": {
                "__v": {
                    "type": "long"
                },
                "createdAt": {
                    "type": "date"
                },
                "deleted": {
                    "type": "date"
                },
                "mediaType": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "meta": {
                    "properties": {
                        "content-type": {
                            "type": "text",
                            "fields": {
                                "keyword": {
                                    "type": "keyword",
                                    "ignore_above": 256
                                }
                            }
                        },
                        "width": {
                            "type": "long"
                        },
                        "height": {
                          "type": "long"
                      }
                    }
                },
                "name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "originalName": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "updatedAt": {
                    "type": "date"
                }
            }
        },
        "settings": {
            "index": {
                "creation_date": "1575884312237",
                "number_of_shards": "1",
                "number_of_replicas": "1",
                "uuid": "nSiAoIIwQJqXQRTyqw9CSA",
                "version": {
                    "created": "7030099"
                },
                "provided_name": "assets"
            }
        }
    }
}

【问题讨论】:

  • 您能发布您的索引映射和设置吗?
  • @tomslabbaert 我已经更新了我的问题以包含映射和设置

标签: elasticsearch elasticsearch-query


【解决方案1】:

对于这个简单的查询,您没有必要使用通配符表达式。

首先,在name 字段上更改您的分析器。

您需要创建一个自定义分析器,将. 替换为space,因为默认标准分析器不会这样做,因此您在搜索test 时会得到test.png,因为两者都会有@987654326 @ 和 png 在倒排索引中。 这样做的主要好处是避免了非常昂贵的正则表达式查询

使用自定义分析器更新了映射,可以为您完成工作。只需更新您的映射并重新索引所有文档。

{
    "aliases": {},
    "mappings": {
        "properties": {
            "__v": {
                "type": "long"
            },
            "createdAt": {
                "type": "date"
            },
            "deleted": {
                "type": "date"
            },
            "mediaType": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "meta": {
                "properties": {
                    "content-type": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "width": {
                        "type": "long"
                    },
                    "height": {
                        "type": "long"
                    }
                }
            },
            "name": {
                "type": "text",
                "analyzer" : "my_analyzer"
            },
            "originalName": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "updatedAt": {
                "type": "date"
            }
        }
    },
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "standard",
                    "char_filter": [
                        "replace_dots"
                    ]
                }
            },
            "char_filter": {
                "replace_dots": {
                    "type": "mapping",
                    "mappings": [
                        ". => \\u0020"
                    ]
                }
            }
        },
        "index": {
            "number_of_shards": "1",
            "number_of_replicas": "1"
        }
    }
}

其次,您应该将查询更改为 bool 查询,如下所示:

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "test"
                    }
                },
                {
                    "match": {
                        "mediaType.keyword": "IMAGE"
                    }
                }
            ]
        }
    }
}

将 must 与 2 个匹配查询一起使用意味着,只有在 must 查询的所有子句中都存在匹配时才会返回文档。

我已经通过创建索引、插入一些示例文档并查询它们来测试我的解决方案,如果您需要任何帮助,请告诉我。

【讨论】:

  • 感谢详细的解释和解答!这行得通。
  • @Ronnyvdb 很高兴知道这一点
【解决方案2】:

您尝试过 best_fields 吗?

{
  "query": {
    "multi_match" : {
      "query":      "Will Smith",
      "type":       "best_fields",
      "fields":     [ "name", "mediaType" ],
      "operator":   "and" 
    }
  }
}

【讨论】:

  • 感谢您的建议,但仍然返回 0 个结果
猜你喜欢
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 2019-12-06
相关资源
最近更新 更多