简体   繁体   English

使用 ElasticSearch 7.x 进行精确搜索

[英]Exact search with ElasticSearch 7.x

I am trying to find an exact search for an url with ElasticSearch ("@elastic/elasticsearch": "^7.5.0").我正在尝试使用 ElasticSearch ("@elastic/elasticsearch": "^7.5.0") 找到对 url 的精确搜索。 I have configured my mapping like so:我已经像这样配置了我的映射:

const schema = {
      userId: {
        type: "keyword"
      },
      url: {
        type: "keyword",
        index: false,
        analyzer: 'keyword'
      },
      pageTitle: {
        type: 'text',
      },
      pageText: {
        type: 'text',
      }
    };

    await client.indices.putMapping({
      index,
      type,
      include_type_name: true,
      body: {
        properties: schema
      }
    })

I have tried different queries, and they looks like this:我尝试了不同的查询,它们看起来像这样:

body: {
        query: {
          bool: {
            must: {
              match: {
                query: 'test stack',
                analyzer: 'keyword',  
              }
            }
          }
        }
      }

Or second attempt:或第二次尝试:

body: {
        query: {
          constant_score: {
            filter: {
              bool: {
                must: {
                  term: {
                    url: 'test stack'
                  } 
                }
              }
            }
          },

        }
      }

None of them work.他们都没有工作。 I want to get only the results where the exact string 'test/stack' is found.我只想获得找到确切字符串 'test/stack' 的结果。 Any help would be highly appreciated.任何帮助将不胜感激。

Example of data I'm trying to add:我尝试添加的数据示例:

[
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
},
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
},
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
}
]

Thanks.谢谢。

I managed to make this work.我设法完成了这项工作。 Steps are: 1. Delete the index.步骤是: 1. 删除索引。 2. Delete the custom mapping function. 2.删除自定义映射功能。 3. Create the index (with client.indices.create) 4. Index the first item (with client.index). 3. 创建索引(使用 client.indices.create) 4. 索引第一项(使用 client.index)。 5. At this point, you can check in postman the dynamic mappings created by ElasticSearch (only visible after 1st item is indexed, by what I could tell). 5. 此时,您可以在邮递员中检查由 ElasticSearch 创建的动态映射(据我所知,仅在第 1 个项目被索引后可见)。 You can make a get request at http://localhost:9200/history/_mappings , and the response should look something like this:你可以在http://localhost:9200/history/_mappings发出一个 get 请求,响应应该是这样的:

{
    "history": {
        "mappings": {
            "properties": {
                "fullTitle": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "log": {
                    "properties": {
                        "startTime": {
                            "type": "long"
                        },
                        "timeSpent": {
                            "type": "long"
                        }
                    }
                },
                "protocol": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "text": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "totalTimeSpent": {
                    "type": "long"
                },
                "totalVisits": {
                    "type": "long"
                },
                "url": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "userId": {
                    "type": "long"
                }
            }
        }
    }
}

As you can see, any field indexed as text has attached another field, called keyword, which can be used for exact matches.如您所见,任何索引为文本的字段都附加了另一个字段,称为关键字,可用于精确匹配。 6. The query to get the exact matches looks like this: 6. 获取精确匹配的查询如下所示:

   const result = await esClient.search({
      index: 'history',
      body: {
        query: {
          term: {
            'url.keyword': {
              value: toInsert.url
            }
          }
        }
      }
    })

At this point you should receive results only in case of exact match for the field "url" in my case.在这一点上,只有在我的情况下与字段“url”完全匹配的情况下,您才应该收到结果。 Hope this helps somebody else.希望这对其他人有帮助。 Thanks @ibexit for trying to help me.感谢@ibexit 试图帮助我。

I see two problems:我看到两个问题:

  1. The mapping defined for the url field says为 url 字段定义的映射说

    url: { type: "keyword", index: false, analyzer: 'keyword' }, url: { type: "keyword", index: false, 分析器: 'keyword' },

    If you define index: false , the field will not be searchable at all.如果您定义index: false ,则该字段将根本不可搜索。 Using the following mapping should work properly:使用以下映射应该可以正常工作:

    url: { type: "keyword" }网址:{ 类型:“关键字”}

    See https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html for more detailed information有关更多详细信息,请参阅https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html

  2. The keyword mapped fields will not match using the match query which is designed to query text fields.关键字映射字段将不匹配使用旨在查询文本字段的match查询。 Please use the term query instead for keyword fields.请对关键字字段使用术语查询。 Please notice the example below using the Elasticseaech Query API:请注意以下使用 Elasticseaech 查询 API 的示例:

    GET /_search { "query": { "term": { "url": { <<= the field to search "value": "test stack" <<= the searched value } } } GET /_search { "query": { "term": { "url": { <<= 要搜索的字段 "value": "test stack" <<= 搜索到的值 } } }
    } }

    Here is the according documentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html这是相应的文档: https : //www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

BTW: keep in mind that you need to reindex the data after a mapping change顺便说一句:请记住,您需要在映射更改后重新索引数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM