繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM