[英]Why does my query using a MinHash analyzer fail to retrieve duplicates?
我正在尝试使用其MinHash 实现查询 Elasticsearch 索引以查找近重复项。 我使用在容器中运行的 Python 客户端来索引和执行搜索。
我的语料库是一个有点像这样的 JSONL 文件:
{"id":1, "text":"I'd just like to interject for a moment"}
{"id":2, "text":"I come up here for perception and clarity"}
...
我成功创建了一个 Elasticsearch 索引,尝试使用自定义设置和分析器,从官方示例和MinHash 文档中汲取灵感:
def create_index(client):
client.indices.create(
index="documents",
body={
"settings": {
"analysis": {
"filter": {
"my_shingle_filter": {
"type": "shingle",
"min_shingle_size": 5,
"max_shingle_size": 5,
"output_unigrams": False
},
"my_minhash_filter": {
"type": "min_hash",
"hash_count": 10,
"bucket_count": 512,
"hash_set_size": 1,
"with_rotation": True
}
},
"analyzer": {
"my_analyzer": {
"tokenizer": "standard",
"filter": [
"my_shingle_filter",
"my_minhash_filter"
]
}
}
}
},
"mappings": {
"properties": {
"name": {"type": "text", "analyzer": "my_analyzer"}
}
},
},
ignore=400,
)
我通过 Kibana 验证索引创建没有大问题,还通过访问http://localhost:9200/documents/_settings我得到了一些看起来有序的东西:
但是,查询索引:
def get_duplicate_documents(body, K, es):
doc = {
'_source': ['_id', 'body'],
'size': K,
'query': {
"match": {
"body": {
"query": body,
"analyzer" : "my_analyzer"
}
}
}
}
res = es.search(index='documents', body=doc)
top_matches = [hit['_source']['_id'] for hit in res['hits']['hits']]
我的res['hits']
一直是空的,即使我将我的body
设置为与我的语料库中的一个条目的文本完全匹配。 换句话说,如果我尝试作为body
的值,我不会得到任何结果,例如
"I come up here for perception and clarity"
或类似的子串
"I come up here for perception"
虽然理想情况下,我希望程序返回近似重复项,其分数是通过 MinHash 获得的查询和近似重复项的 Jaccard 相似度的近似值。
我的查询和/或索引 Elasticsearch 的方式有问题吗? 我完全错过了其他东西吗?
PS:你可以看看https://github.com/davidefiocco/dockerized-elasticsearch-duplicate-finder/tree/ea0974363b945bf5f85d52a781463fba76f4f987一个非功能性的,但希望可重现的例子(我也会更新回购协议,因为我找到了解决方案!)
以下是您应该仔细检查的一些事项,因为它们很可能是罪魁祸首:
当您创建映射时,您应该在body
参数内的client.indices.create
方法中从“name”更改为“text”,因为您的 json 文档有一个名为text
的字段:
"mappings": { "properties": { "text": {"type": "text", "analyzer": "my_analyzer"} }
在索引阶段,您还可以按照文档修改您的generate_actions()
方法,例如:
for elem in corpus: yield { "_op_type": "index" "_index": "documents", "_id": elem["id"], "_source": elem["text"] }
顺便说一下,如果你正在索引pandas
数据帧,你可能需要检查实验官方库eland 。
此外,根据您的映射,您正在使用minhash
令牌过滤器,因此 Lucene 将在 hash 中的text
字段内转换您的文本。因此您可以使用 hash 查询此字段,而不是像您在示例中所做的那样使用字符串"I come up here for perception and clarity"
。 所以最好的使用方法是检索字段text
的内容,然后在 Elasticsearch 中查询检索到的相同值。 然后_id
元字段不在_source
元字段内,因此您应该更改get_duplicate_documents()
方法:
def get_duplicate_documents(body, K, es): doc = { '_source': ['text'], 'size': K, 'query': { "match": { "text": { # I changed this line: "query". body } } } } res = es,search(index='documents', body=doc) # also changed the list comprehension! top_matches = [(hit['_id'], hit['_source']) for hit in res['hits']['hits']]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.