假设我有3个文档,每个文档仅包含一个字段(但让我们想象还有更多,我们需要搜索所有字段)。
这是一个可用于创建这三个文档的脚本:
# 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"}'
我需要找到唯一一个在其一个字段中具有“第一秒”文本的文档(文档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,因为它们都包含“第一第二”。
https://stackoverflow.com/a/28024714/7637120在这里,他们建议在建立索引时使用“关键字”分析器来分析字段,但是我想避免对映射进行任何自定义。
是否有可能避免它们而仍然只找到文档1?
答案 0 :(得分:1)
是的,您可以通过将name
映射类型声明为keyword
来实现。解决问题的关键很简单-声明name
映射type: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"
}
查询
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"
}
}
]
}
}
添加第二个解决方案
(如果name
不是keyword
类型,而是text
类型。这里只有fielddata:true
才需要在name
字段中添加)>
映射
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"
}
}
]
}
}
答案 1 :(得分:1)
在Elasticsearch 7.1.0中,即使您没有创建特殊的映射,似乎也可以使用keyword
分析器。至少我没有,以下查询可以满足我的需求:
curl -H 'Content-Type: application/json' -iX POST 'http://localhost:9200/test/_search' -d '{
"query": {
"query_string": {
"query": "first second",
"analyzer": "keyword"
}
}
}'