我正在尝试使用MinHash implementation查询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索引,尝试使用自定义设置和分析器,并从official examples和MinHash docs中汲取了灵感: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的方式有问题吗?我是否完全想念其他东西?
P.S .:您可以查看https://github.com/davidefiocco/dockerized-elasticsearch-duplicate-finder/tree/ea0974363b945bf5f85d52a781463fba76f4f987作为非功能性但希望可复制的示例(在找到解决方案时,我还将更新存储库!)
最佳答案
您应该仔细检查以下几件事,因为它们很可能是罪魁祸首:
client.indices.create
参数内的body
方法中将“名称”更改为“文本”,因为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
token 过滤器,因此Lucene会在哈希的text
字段内转换您的文本。因此,您可以使用哈希而不是字符串来查询该字段,就像在示例"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']]
关于python - 为什么使用MinHash分析器的查询无法检索重复项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63221732/