python - 为什么使用MinHash分析器的查询无法检索重复项?

标签 python elasticsearch duplicates elasticsearch-py minhash

我正在尝试使用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 examplesMinHash 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,我得到了一些有序的信息:
enter image description here
但是,使用以下方法查询索引:
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"}
          }
    
  • 在建立索引阶段的
  • 中,您还可以按照类似the documentation的方式对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/

    相关文章:

    python - 如何将 PyInstaller 包含在 PyInstaller 包中?

    python - Plotly:使用循环添加轨迹

    elasticsearch - 如何在 Elasticsearch 中的现有映射中添加新字段时添加默认值

    elasticsearch - elasticsearch中的文档被自动删除?

    javascript - 在javascript数组中排序和删除重复项(仅显示最新值)

    mysql - ON DUPLICATE KEY UPDATE 每列,除了

    python - 与 COM (python) 的 MSMQ 事务?

    python - 为什么python使用redis这么慢?

    docker - 无法启动logstash

    java - java中两个字符串的字符串长度错误?