Elasticsearch -在文本和关键字字段中搜索标点符号术语

vsaztqbk  于 2023-02-11  发布在  ElasticSearch
关注(0)|答案(1)|浏览(217)

在使用elasticsearch 7时,我尝试使用simple query string query来搜索不同的字段,包括textkeyword。下面是一个最小的、可重现的示例,以显示初始设置和问题:
mapping.json:

{
    "dynamic": false,
    "properties": {
        "publicId": {
            "type": "keyword"
        },
        "eventDate": {
            "type": "date",
            "format": "yyyy-MM-dd",
            "fields": {
                "keyword": {
                    "type": "keyword"
                }
            }
        },
        "name": {
            "type": "text"
        }
    }
}

test-data1.json:

{
    "publicId": "a1b2c3",
    "eventDate": "2022-06-10",
    "name": "Research & Development"
}

test-data2.json

{
    "publicId": "d4e5f6",
    "eventDate": "2021-05-11",
    "name": "F.inance"
}

在本地主机19200上运行的ES上创建索引:

#!/bin/bash -e

host=${1-localhost:19200}
dir=$( dirname `readlink -f $0` )

mapping=$(<${dir}/mapping.json);

param="{ \"mappings\": $mapping}"

curl -XPUT "http://${host}/test/" -H 'Content-Type: application/json' -d "$param"
curl -XPOST "http://${host}/test/_doc/a1b2c3" -H 'Content-Type: application/json' -d @${dir}/test-data1.json
curl -XPOST "http://${host}/test/_doc/d4e5f6" -H 'Content-Type: application/json' -d @${dir}/test-data2.json

现在的任务是支持像"研发","研发2022 - 06 - 10","金融"(注意删除的点)或简单的"a1b2c3"这样的搜索。例如,使用这样的查询:

{
    "from": 0,
    "size": 20,
    "query": {
        "bool": {
            "must": [
                {
                    "simple_query_string": {
                        "query": "Research & Development 2022-06-10",
                        "fields": [
                            "publicId^1.0",
                            "eventDate.keyword^1.0",
                            "name^1.0"
                        ],
                        "flags": -1,
                        "default_operator": "and",
                        "analyze_wildcard": false,
                        "auto_generate_synonyms_phrase_query": true,
                        "fuzzy_prefix_length": 0,
                        "fuzzy_max_expansions": 50,
                        "fuzzy_transpositions": true,
                        "boost": 1.0
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1.0
        }
    },
    "version": true
}

这种设置的问题在于,文本字段的standard analyzer删除了大部分标点符号,当然也删除了"与"字符。简单的查询字符串查询将查询拆分为三个标记[research, &, development],并使用and运算符搜索所有字段。("Research"和"Development"),但在任何字段中都没有与"and"匹配的项。因此结果为空。
现在,我想到了一个解决方案:使用另一个分析器whitespace analyzername添加第二个字段,该分析器不会删除标点符号:

{
    "dynamic": false,
    "properties": {
        "publicId": {
            "type": "keyword"
        },
        "eventDate": {
            "type": "date",
            "format": "yyyy-MM-dd",
            "fields": {
                "keyword": {
                    "type": "keyword"
                }
            }
        },
        "name": {
            "type": "text",
            "fields": {
                "whitespace": {
                    "type": "text",
                    "analyzer": "whitespace"
                }
            }
        }
    }
}

这样,所有搜索都可以正常工作,包括与name字段的"F. inance"匹配的"Finance"。此外,"Research & Development"与name字段和name.whitespace匹配,但最关键的是&name.whitespace匹配,因此返回结果。
我现在的问题是:给定实际设置包括更多字段和大量数据的事实,添加附加字段并因此以相同方式索引大多数项两次似乎相当繁重。是否有办法仅将与标准分析器的项name不同的被分析项索引到name.whitespace,即不在"父"字段中?例如,"研发"导致name的术语[research, development]name.whitespace的术语[research, development, &]-理想地,它将仅索引[&]以得到name.whitespace
或者有没有一个更优雅/性能更好的解决方案来解决这个特定的问题?

ewm0tg9j

ewm0tg9j1#

我想你可以为所有的字符串字段定义一个动态属性Map,并使用空白分析器,因为你的用例有搜索非标准标记的规范,另外,你可以在Map中指定那些你不需要空白标记器的字段。
这将确保使用标准标记器分析已经Map的字段,而使用空白分析其他字段(动态或未Map字段),从而减少复杂性、字段重复等。

相关问题