Я разработал небольшой пример (при условии, что вы используете ES 5.x из-за разницы в подсчете очков):
DELETE test
PUT test
{
"settings": {
"similarity": {
"my_bm25": {
"type": "BM25",
"b": 0
}
}
},
"mappings": {
"test": {
"properties": {
"name": {
"type": "text",
"similarity": "my_bm25",
"fields": {
"length": {
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
}
}
POST test/test/1
{
"name": "John Rham Rham"
}
POST test/test/2
{
"name": "John Rham Rham Luck"
}
GET test/_search
{
"query": {
"function_score": {
"query": {
"match": {
"name": {
"query": "John Rham Rham",
"operator": "and"
}
}
},
"functions": [
{
"script_score": {
"script": "_score / doc['name.length'].getValue()"
}
}
]
}
}
}
Этот код делает следующее:
- Замените реализацию BM25 по умолчанию на пользовательскую, изменив параметр B (нормализация длины поля). Вы также можете изменить сходство с «классическим», чтобы вернуться к TF/IDF, в котором нет этой нормализации.
- Создайте внутреннее поле для поля вашего имени, которое подсчитывает количество токенов внутри поля вашего имени.
- Обновите счет в соответствии с длиной токена
Это приведет к:
"hits": {
"total": 2,
"max_score": 0.3596026,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 0.3596026,
"_source": {
"name": "John Rham Rham"
}
},
{
"_index": "test",
"_type": "test",
"_id": "2",
"_score": 0.26970196,
"_source": {
"name": "John Rham Rham Luck"
}
}
]
}
}
Не уверен, что это лучший способ сделать это, но, возможно, он укажет вам правильное направление :)
person
Byron Voorbach
schedule
12.04.2017