elasticsearch 在Elasticsearch的所有字段中按精确匹配进行搜索
假设我有3个文档,每个文档只包含一个字段(但假设还有更多文档,我们需要搜索所有字段)elasticsearch 在Elasticsearch的所有字段中按精确匹配进行搜索,elasticsearch,exact-match,elasticsearch,Exact Match,假设我有3个文档,每个文档只包含一个字段(但假设还有更多文档,我们需要搜索所有字段) 字段值为“第一秒” 字段值为“第二优先” 字段值为“第一个第二个第三个” 以下是可用于创建这3个文档的脚本: # drop the index completely, use with care! curl -iX DELETE 'http://localhost:9200/test' curl -H 'content-type: application/json' -iX PUT 'http://local
# drop the index completely, use with care!
curl -iX DELETE 'http://localhost:9200/test'
curl -H 'content-type: application/json' -iX PUT 'http://localhost:9200/test/_doc/one' -d '{"name":"first second"}'
curl -H 'content-type: application/json' -iX PUT 'http://localhost:9200/test/_doc/two' -d '{"name":"second first"}'
curl -H 'content-type: application/json' -iX PUT 'http://localhost:9200/test/_doc/three' -d '{"name":"first second third"}'
我需要找到唯一一个在其中一个字段中有“first second”文本的文档(文档1)
这是我试过的
A.普通搜索:
curl -H 'Content-Type: application/json' -iX POST 'http://localhost:9200/test/_search' -d '{
"query": {
"query_string": {
"query": "first second"
}
}
}'
返回所有3个文档
B.引用
curl -H 'Content-Type: application/json' -iX POST 'http://localhost:9200/test/_search' -d '{
"query": {
"query_string": {
"query": "\"first second\""
}
}
}'
给出2个文档:1和3,因为它们都包含“first second”
在这里,他们建议在索引时使用“关键字”分析器来分析字段,但我希望避免对映射进行任何自定义
是否可以避免它们,但仍然只能找到文档1?是的,您可以通过将
名称
映射类型声明为关键字
来实现这一点。解决问题的关键很简单——声明name
mappingtype:keyword
然后离开
为了证明这一点,我已经做了这些
1) created mapping with `keyword` for `name` field`
2) indexed the three documents
3) searched with a `match` query
映射
PUT so_test16
{
"mappings": {
"_doc":{
"properties":{
"name": {
"type": "keyword"
}
}
}
}
}
POST /so_test16/_doc
{
"id": 1,
"name": "first second"
}
POST /so_test16/_doc
{
"id": 2,
"name": "second first"
}
POST /so_test16/_doc
{
"id": 3,
"name": "first second third"
}
PUT so_test18
{
"mappings" : {
"_doc" : {
"properties" : {
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fielddata": true
}
}
}
}
}
为文档编制索引
PUT so_test16
{
"mappings": {
"_doc":{
"properties":{
"name": {
"type": "keyword"
}
}
}
}
}
POST /so_test16/_doc
{
"id": 1,
"name": "first second"
}
POST /so_test16/_doc
{
"id": 2,
"name": "second first"
}
POST /so_test16/_doc
{
"id": 3,
"name": "first second third"
}
PUT so_test18
{
"mappings" : {
"_doc" : {
"properties" : {
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fielddata": true
}
}
}
}
}
查询
GET /so_test16/_search
{
"query": {
"match": {"name": "first second"}
}
}
和结果
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "so_test16",
"_type" : "_doc",
"_id" : "m1KXx2sB4TH56W1hdTF9",
"_score" : 0.2876821,
"_source" : {
"id" : 1,
"name" : "first second"
}
}
]
}
}
添加第二个解决方案
(如果名称
不是关键字
类型,而是文本
类型。这里只有字段数据:名称
字段也需要添加true
)
映射
PUT so_test16
{
"mappings": {
"_doc":{
"properties":{
"name": {
"type": "keyword"
}
}
}
}
}
POST /so_test16/_doc
{
"id": 1,
"name": "first second"
}
POST /so_test16/_doc
{
"id": 2,
"name": "second first"
}
POST /so_test16/_doc
{
"id": 3,
"name": "first second third"
}
PUT so_test18
{
"mappings" : {
"_doc" : {
"properties" : {
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fielddata": true
}
}
}
}
}
和搜索查询
GET /so_test18/_search
{
"query": {
"bool": {
"must": [
{"match_phrase": {"name": "first second"}}
],
"filter": {
"script": {
"script": {
"lang": "painless",
"source": "doc['name'].values.length == 2"
}
}
}
}
}
}
和响应
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.3971361,
"hits" : [
{
"_index" : "so_test18",
"_type" : "_doc",
"_id" : "o1JryGsB4TH56W1hhzGT",
"_score" : 0.3971361,
"_source" : {
"id" : 1,
"name" : "first second"
}
}
]
}
}
在Elasticsearch 7.1.0中,您似乎可以使用
关键字
分析器,即使不创建特殊映射。至少我没有,下面的查询满足了我的需要:
curl -H 'Content-Type: application/json' -iX POST 'http://localhost:9200/test/_search' -d '{
"query": {
"query_string": {
"query": "first second",
"analyzer": "keyword"
}
}
}'
谢谢你@JBone。但是如果我不控制映射,并且我不知道文档中将存在的确切字段,该怎么办?在这种情况下,有没有一种方法可以使用“精确匹配”进行搜索?似乎在不知道
映射的情况下,我想这很难,但是如果您想尝试我答案中的第二种解决方案,请尝试。这里的内容是在映射
中,对于名称
字段,我需要添加fielddata=true
,脚本才能工作。谁知道你的<代码>映射< /代码>可能已经考虑<代码>字段数据=true< /Cord>,所以你可以试着运行第二个解决方案。通过你的url/index/\u映射
向我们展示映射
实际上,我很想找到一种不需要对映射进行任何操作的搜索方法。我还没有任何已知的映射,这就像一个研发任务,所以还没有什么可以展示的,唉,太好了。在新版本的Elastic(7.2版)中,他们添加了match\u bool\u prefix
,这可能会解决您的问题(通过让analyzer处于查询级别而不是映射级别),我们可以尝试一下。我的机器上有6.7版本,所以我需要得到这个新的Elasticsearch。但是一定要通过这个链接来理解我在说什么。谢谢,我来看看