gpt4 book ai didi

python - 在 Elasticsearch 中搜索句点和连字符分隔的字段

转载 作者:行者123 更新时间:2023-12-03 01:34:36 26 4
gpt4 key购买 nike

我正在尝试找到一种方法来使用 Elasticsearch 来查询以句点和连字符分隔的字段。

我有一个像这样的(MySQL)数据集(使用 SQLAlchemy 访问它):

id    text        tag
====================================
1 some-text A.B.c3
2 more. text A.B-C.c4
3 even more. B.A-32.D-24.f9

我首先使用 ES 进行搜索的核心原因是我想查询 text field 。那部分效果很棒!

但是,(我认为)我想要 tag像这样出现在倒排索引中(我可能不会考虑大小写,只是为了说明而包括它):
A.B.c3            1
A.B-C.c4 2
B.A-C2.D-24.f9 3

然后,我想搜索 tag像这样的字段:
{ "query": {
"prefix" : { "tag" : "A.B" }
}
}

并让查询返回 id/行/文档 1 和 2。

基本上,我希望查询匹配这个真值表中的索引:
"A." = 1, 2
"A-" = 3

如何在开头同时完成“ A.”匹配,区分句点和连字符(可能会增强它),并根据这些相同的分隔符匹配中间短语?

如果这些匹配出现在 tag 的开头,我还想将它们加权得更高。如果可能的话。

我该怎么做,或者 Elasticsearch 不是适合这项工作的工具?似乎 Elasticsearch 非常适合我对通常分隔的英文文本的文本字段比较,但基于标签的搜索似乎要困难得多。

更新:似乎当我只索引我的搜索返回的结果的数据的子集时,但是当查询完整的数据集时,我得到的命中更少。

最佳答案

这可以通过 N-Gram 完成分词器。

根据您提供的内容,我创建了相应的映射、文档和示例查询,为您提供所需的内容。

映射

PUT idtesttag
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 2,
"max_gram": 5
}
}
}
},
"mappings": {
"mydocs": {
"properties": {
"id": {
"type": "long"
},
"text": {
"type": "text",
"analyzer": "my_analyzer"
},
"tag": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
}

如果您有一个带有 id = 1 的文档,这将做有标签 A.B它将以下一组字符存储在其倒排索引中。
 A. -> 1
.B -> 1
A.B -> 1

因此,如果您的查询包含这三个词中的任何一个,则您的文档为 id=1将被退回。

样本文件
POST idtesttag/mydocs/1
{
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}

POST idtesttag/mydocs/2
{
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}

POST idtesttag/mydocs/3
{
"id": 3,
"text": "even more.",
"tag": "B.A-32.D-24.f9"
}

POST idtesttag/mydocs/4
{
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}

示例查询
POST idtesttag/_search
{
"query": {
"match": {
"tag": "A.B"
}
}
}

查询响应
{
"took": 139,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.8630463,
"hits": [
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "1",
"_score": 0.8630463,
"_source": {
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "2",
"_score": 0.66078395,
"_source": {
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "4",
"_score": 0.46659434,
"_source": {
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}
}
]
}
}

请注意,文档 1、2 和 4 在响应中返回。 document 4是中间句子匹配,而文档 1 & 2是在开始。

还要注意分数值的显示方式。

基于炒作的提升

现在关于基于 hypen 的提升性格,我建议你有 BoolRegex Query with Boosting 一起查询.以下是我提出的示例查询。

请注意,为了简单起见,我添加了正则表达式,只有当 hypen 位于 A.B 旁边时它才会增强。 .
POST idtesttag/_search
{
"query": {
"bool": {
"must" : {
"match" : { "tag" : "A.B" }
},
"should": [
{
"regexp": {
"tag": {
"value": "A.B-.*",
"boost": 3
}
}
}
]
}
}
}

提高查询响应
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 3.660784,
"hits": [
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "2",
"_score": 3.660784,
"_source": {
"id": 2,
"text": "more. text",
"tag": "A.B-C.c4"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "4",
"_score": 3.4665942,
"_source": {
"id": 3,
"text": "even more.",
"tag": "B.A.B-32.D-24.f9"
}
},
{
"_index": "idtesttag",
"_type": "mydocs",
"_id": "1",
"_score": 0.8630463,
"_source": {
"id": 1,
"text": "some-text",
"tag": "A.B.c3"
}
}
]
}
}

只需确保您的测试在提升方面是彻底的,因为这一切都与影响分数有关,并确保您使用 DEV/TEST Elastic 索引中摄取的 prod 数据来做到这一点。

这样一来,如果您转向 PROD Elastic,当您看到完全不同的结果时,您就不会感到害怕。

对不起,它的答案很长,但我希望这会有所帮助!

关于python - 在 Elasticsearch 中搜索句点和连字符分隔的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53385768/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com