elasticsearch 对嵌套字段进行筛选的KNN查询的意外结果

yvgpqqbh  于 2023-08-03  发布在  ElasticSearch
关注(0)|答案(1)|浏览(108)

我有一个索引:

"properties": {
    "id": {"type": "text"},
    "date": {"type": "text"},
    "title": {"type": "text"},
    "users": {"type": "nested"},
    "ideas": {
        "type": "nested",
        "properties": {
            "vector": {
                "type": "knn_vector",
                "dimension": 384
            },
            "timestamp": {"type": "integer"},
            "content": {
                "type": "keyword", 
            },
        }
    }
}

字符串
以下查询搜索与给定向量具有高相似性的想法:

body={
    "_source": {
        "includes": [
            "title",
            "users",
            "ideas._score"
        ]
    },
    "size": 1,
    "query": {
        "bool": {
            "must": [
                {
                    "nested": {
                        "path": "ideas",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "script_score": {
                                            "query": {
                                                "match_all": {}
                                            },
                                            "script": {
                                                "source": "knn_score",
                                                "lang": "knn",
                                                "params": {
                                                    "field": "ideas.vector",
                                                    "query_value": query_vector,
                                                    "space_type": "cosinesimil"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}


它在输出中返回以下内容:

{"hits": "_id": "kHCOaIkBUHe9xr-u09Xr", "_score": 1.1901431, "_source": {"title": "doc1", "users": [{"id": "user1"}]}}


现在,我修改上面的查询,只考虑特定用户有权访问的文档:

body={
    "_source": {
        "includes": [
            "title",
            "users",
            "ideas._score"
        ]
    },
    "size": 1,
    "query": {
        "bool": {
            "must": [
                {
                    "nested": {
                        "path": "users",
                        "query": {
                            "match_phrase": {
                                "users.id": user_id
                            }
                        }
                    }
                },
                {
                    "nested": {
                        "path": "ideas",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "script_score": {
                                            "query": {
                                                "match_all": {}
                                            },
                                            "script": {
                                                "source": "knn_score",
                                                "lang": "knn",
                                                "params": {
                                                    "field": "ideas.vector",
                                                    "query_value": query_vector,
                                                    "space_type": "cosinesimil"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}


当我将“user1”作为感兴趣的用户传递给这个查询时,我希望看到与第一个查询相同的输出。但我看到了不同的东西:

{"hits": "_id": "kXCOaIkBUHe9xr-u2tV1", "_score": 2.866434, "_source": {"title": "doc2", "users": [{"id": "user1"}]}}


事实上,通过这种过滤,即使对于绝对不相关的查询,分数也很高。此外,分数应该在1和2之间,所以分数2.866434应该永远不会发生。
为什么会这样?

pepwfjgg

pepwfjgg1#

我会在bool/filter节中添加user.id上的第一个嵌套约束,而不是bool/must,因为它不应该对评分有贡献,如下所示:

body={
    "_source": {
        "includes": [
            "title",
            "users",
            "ideas._score"
        ]
    },
    "size": 1,
    "query": {
        "bool": {
            "filter": [
                {
                    "nested": {
                        "path": "users",
                        "query": {
                            "term": {
                                "users.id": user_id
                            }
                        }
                    }
                }
            ],
            "must": [
                {
                    "nested": {
                        "path": "ideas",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "script_score": {
                                            "query": {
                                                "match_all": {}
                                            },
                                            "script": {
                                                "source": "knn_score",
                                                "lang": "knn",
                                                "params": {
                                                    "field": "ideas.vector",
                                                    "query_value": query_vector,
                                                    "space_type": "cosinesimil"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}

字符串
您添加到bool/must的任何约束都有助于通过设计进行评分。如果你不想让你的附加约束影响评分,你可以简单地将它们添加到过滤器部分。
类似地,您还可以在script_score查询中添加额外的约束,以减少knn搜索必须处理的文档集:

body={
    "_source": {
        "includes": [
            "title",
            "users",
            "ideas._score"
        ]
    },
    "size": 1,
    "query": {
        "bool": {
            "must": [
                {
                    "nested": {
                        "path": "ideas",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "script_score": {
                                            "query": {
                                               "term": {
                                                  "users.id": user_id
                                               }                                                
                                            },
                                            "script": {
                                                "source": "knn_score",
                                                "lang": "knn",
                                                "params": {
                                                    "field": "ideas.vector",
                                                    "query_value": query_vector,
                                                    "space_type": "cosinesimil"
                                                }
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}

相关问题