Étant donné l'indice suivant

PUT /test_index
{
    "mappings": {
        "properties": {
        "field1": { 
            "type": "text",
            "analyzer": "whitespace",
            "similarity": "boolean"
        },
        "field2": { 
            "type": "text",
            "analyzer": "whitespace",
            "similarity": "boolean"
        }
        }
    }
}

Et les données suivantes

POST /test_index/_bulk?refresh=true
{ "index" : {} }
{ "field1": "foo", "field2": "bar"}
{ "index" : {} }
{ "field1": "foo1 foo2", "field2": "bar1 bar2"}
{ "index" : {} }
{ "field1": "foo1 foo2 foo3", "field2": "bar1 bar2 bar3"}

Pour la requête de similarité booléenne donnée

POST /test_index/_search
{
    "size": 10,
    "min_score": 0.4,
    "query": {
        "function_score": {
        "query": {
            "bool": {
            "should": [
                {
                "fuzzy":{
                    "field1":{
                        "value":"foo",
                        "fuzziness":"AUTO",
                        "boost": 1
                    }
                }
            },
            {
                "fuzzy":{
                    "field2":{
                        "value":"bar",
                        "fuzziness":"AUTO",
                        "boost": 1
                    }
                }
            }
            ]
            }
        }
        }
    }
}

Je reçois toujours ["foo1 foo2 foo3", "bar1 bar2 bar3"] malgré le fait qu'il y ait un résultat exact dans index (le premier):

{
    "took": 114,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 3.9999998,
        "hits": [
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "bXw8eXUBCTtfNv84bNPr",
                "_score": 3.9999998,
                "_source": {
                    "field1": "foo1 foo2 foo3",
                    "field2": "bar1 bar2 bar3"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "bHw8eXUBCTtfNv84bNPr",
                "_score": 2.6666665,
                "_source": {
                    "field1": "foo1 foo2",
                    "field2": "bar1 bar2"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "a3w8eXUBCTtfNv84bNPr",
                "_score": 2.0,
                "_source": {
                    "field1": "foo",
                    "field2": "bar"
                }
            }
        ]
    }
}

Je suis conscient du fait que Boolean fonctionne de cette façon pour faire correspondre autant de résultats, et je sais que je peux faire une nouvelle notation ici, mais ce n'est pas une option car je ne sais pas combien de résultats top N à récupérer.

Y a-t-il d'autres options ici? Peut-être pour créer mon propre plugin de similarité basé sur la similarité booléenne pour supprimer les doublons et laisser le jeton le mieux adapté, mais je ne sais pas par où commencer, je ne vois que des exemples pour le script et le rescore.

1
Magic Wand 4 nov. 2020 à 00:09

1 réponse

Meilleure réponse

Mise à jour : sur la base de la clarté fournie dans la section des commentaires de ma réponse précédente, mise à jour de la réponse.

La requête ci-dessous renvoie les résultats attendus

{
    "min_score": 0.4,
    "size":10,
    "query": {
        "function_score": {
            "query": {
                "bool": {
                    "should": [
                        {
                            "fuzzy": {
                                "field1": {
                                    "value": "foo",
                                    "fuzziness": "AUTO",
                                    "boost": 0.5
                                }
                            }
                        },
                        {
                            "term": { --> used for boosting the exact terms
                                "field1": {
                                    "value": "foo",
                                     "boost": 1.5 --> further boosting the exact match.
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
}

Et résultats de recherche

"hits": [
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "zdMEvHUBlo4-1mHbtvNH",
                "_score": 2.0,
                "_source": {
                    "field1": "foo",
                    "field2": "bar"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "z9MEvHUBlo4-1mHbtvNH",
                "_score": 0.99999994,
                "_source": {
                    "field1": "foo1 foo2 foo3",
                    "field2": "bar1 bar2 bar3"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "ztMEvHUBlo4-1mHbtvNH",
                "_score": 0.6666666,
                "_source": {
                    "field1": "foo1 foo2",
                    "field2": "bar1 bar2"
                }
            }
        ]

Une autre requête sans le boost explicite du terme exact renvoie également les résultats attendus

{
    "min_score": 0.4,
    "query": {
        "function_score": {
            "query": {
                "bool": {
                    "should": [
                        {
                            "fuzzy": {
                                "field1": {
                                    "value": "foo",
                                    "fuzziness": "AUTO",
                                    "boost": 0.5
                                }
                            }
                        },
                        {
                            "term": {
                                "field1": {
                                    "value": "foo" --> notice there is no boost
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
}

Et résultat de la recherche

"hits": [
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "zdMEvHUBlo4-1mHbtvNH",
                "_score": 1.5,
                "_source": {
                    "field1": "foo",
                    "field2": "bar"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "z9MEvHUBlo4-1mHbtvNH",
                "_score": 0.99999994,
                "_source": {
                    "field1": "foo1 foo2 foo3",
                    "field2": "bar1 bar2 bar3"
                }
            },
            {
                "_index": "test_index",
                "_type": "_doc",
                "_id": "ztMEvHUBlo4-1mHbtvNH",
                "_score": 0.6666666,
                "_source": {
                    "field1": "foo1 foo2",
                    "field2": "bar1 bar2"
                }
            }
        ]
1
Opster Elasticsearch Ninja 12 nov. 2020 à 10:36