Elasticsearch sorgu sonuçlarını kendi kendine puanlıyor, bu nedenle sizin herhangi birşey yapmanıza gerek yok ama, eğer isterseniz puanlama sistemini direkt olarak manipüle edebilirsiniz. Bu tarz işlemler için boost özelliğini kullanıyoruz. Araba satıcısına "Her ne kadar bwm ve mercedes markalarını eşit derecede sevsemde, eğer bwm alabilirsem daha mutlu olurum, bu nedenle elinden geleni yaparak bana lütfen bwm arabalarını daha önce göster" demeye benziyor.

Query içindeki boost_mode ile oynamadığınız sürece, boost puan hesaplaması yaparken, kısa olan değeri uzun olana nazaran daha yüksek puana tabii tutar. Örnek: Eğer arama kelimeniz "hello" ise, içinde sadece "hello" kelimesi bulunan kayıt, içinde "hello world" olan kayıttan daha yüksek puan alır.


Örnek Elasticsearch verileri


+----+-------------------+
| id | title |
+----+-------------------+
| 1 | one |
| 2 | two |
| 3 | three |
| 4 | one two |
| 5 | one three |
| 6 | one two three |
| 7 | two three |
| 8 | none | <- This will never appear in queries below
| 9 | one abc |
| 10 | two abc |
| 11 | three abc |
| 12 | one two abc |
| 13 | one two three abc |
| 14 | two three abc |
+----+-------------------+
14 rows in set (0.00 sec)

Sorgu 1


Aşağıdaki sorgu "title" alanının içinde "one", "two" veya "three" olan tüm kayıtları listeleyecektir. Ayrıca, puanlama yaparken içinde "three" olan kayıtlar, "two" olanlara göre ve içinde "two" olanlar ise, "one" olanlara göre daha iyi puana tabii tutulacaktır.


curl -XPOST "http://127.0.0.1:9200/_search?post_dev" -d'
{
"query": {
"bool": {
"must": {
"match": {
"title": {
"query": "one two three",
"operator": "or" /* if you remove this line, it would still run OR query because is it default behaviour */
}
}
},
"should": [
{
"match": {
"title": {
"query": "one",
"boost": 1.5
}
}
},
{
"match": {
"title": {
"query": "two",
"boost": 2.5
}
}
},
{
"match": {
"title": {
"query": "three",
"boost": 3.5
}
}
}
]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"from": "0",
"size": "100"
}'

Sonuç


Elasticsearch biraz kompleks puanlama algoritması kullandığı için, her ne kadar bazı kayıtlar diğerlerine nazaran daha değerli verilere sahip olsalar bile, neden daha az puan aldıklarını anlamak veya açıklamak mümkün olmuyor. Bu örnekte geçerli olduğu gibi.


+----+-------------------+
| id | title | ES _score OUR _score
+----+-------------------+
| 6 | one two three | 0.9846948 7.5
| 13 | one two three abc | 0.9846948 7.5
| 4 | one two | 0.5968839 4
| 3 | three | 0.51140535 3.5
| 5 | one three | 0.49692816 5
| 7 | two three | 0.48417675 6
| 14 | two three abc | 0.38734144 6
| 11 | three abc | 0.35777172 3.5
| 12 | one two abc | 0.31694633 4
| 10 | two abc | 0.23624702 2.5
| 2 | two | 0.1286011 2.5
| 1 | one | 0.09882839 1.5
| 9 | one abc | 0.08662249 1.5
+----+-------------------+
13 rows in set (0.00 sec)

Sorgu 2


Aşağıdaki sorgu "title" alanının içinde "one", "two" veya "three" olan tüm kayıtları listeleyecektir. Ayrıca, puanlama yaparken içinde "three" olan kayıtlar, "two" olanlara göre ve içinde "two" olanlar ise, "one" olanlara göre daha iyi puana tabii tutulacaktır.


curl -XPOST "http://127.0.0.1:9200/_search?post_dev" -d'
{
"query": {
"bool": {
"must": {
"match": {
"title": {
"query": "one two three",
"operator": "or" /* if you remove this line, it would still run OR query because is it default behaviour */
}
}
},
"should": [
{
"match": {
"title": {
"query": "one",
"boost": 1.5
}
}
},
{
"match": {
"title": {
"query": "two",
"boost": 2.5
}
}
},
{
"match": {
"title": {
"query": "three",
"boost": 3.5
}
}
}
]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"from": "0",
"size": "10"
}'

Sonuç


Elasticsearch biraz kompleks puanlama algoritması kullandığı için, her ne kadar bazı kayıtlar diğerlerine nazaran daha değerli verilere sahip olsalar bile, neden daha az puan aldıklarını anlamak veya açıklamak mümkün olmuyor. Bu örnekte geçerli olduğu gibi.


+----+-------------------+
| id | title | ES _score OUR _score
+----+-------------------+
| 6 | one two three | 0.762778 7.5
| 13 | one two three abc | 0.762778 7.5
| 4 | one two | 0.43070683 4
| 7 | two three | 0.3947725 6
| 5 | one three | 0.38228768 5
| 3 | three | 0.33812702 3.5
| 14 | two three abc | 0.315818 6
| 11 | three abc | 0.23125261 3.5
| 12 | one two abc | 0.22994567 4
| 10 | two abc | 0.15094957 2.5
| 2 | two | 0.08401244 2.5
| 1 | one | 0.057243854 1.5
| 9 | one abc | 0.050172962 1.5
+----+-------------------+
13 rows in set (0.00 sec)

Sorgu 2 (TAVSİYE EDİLEN)


Aşağıdaki sorgu "title" alanının içinde "one", "two" veya "three" olan tüm kayıtları listeleyecektir. Ayrıca, puanlama yaparken içinde "three" olan kayıtlar, "two" olanlara göre ve içinde "two" olanlar ise, "one" olanlara göre daha iyi puana tabii tutulacaktır.


curl -XPOST "http://127.0.0.1:9200/_search?post_dev" -d'
{
"query": {
"function_score": {
"query": {
"match": {
"title": "one two three"
}
},
"functions": [
{
"filter": {
"query": {
"match": {
"title": "one"
}
}
},
"weight": 1.5
},
{
"filter": {
"query": {
"match": {
"title": "two"
}
}
},
"weight": 2.5
},
{
"filter": {
"query": {
"match": {
"title": "three"
}
}
},
"weight": 3.5
}
],
"score_mode": "sum",
"boost_mode": "replace"
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"from": "0",
"size": "100"
}'

Sonuç


İşte istediğimizde bu sonuç buydu. Aşağıda da gördüğümüz gibi puanlama beklentilerimize uyuyor.


+----+-------------------+
| id | title | ES _score OUR _score
+----+-------------------+
| 6 | one two three | 7.5 7.5
| 13 | one two three abc | 7.5 7.5
| 7 | two three | 6 6
| 14 | two three abc | 6 6
| 5 | one three | 5 5
| 4 | one two | 4 4
| 12 | one two abc | 4 4
| 11 | three abc | 3.5 3.5
| 3 | three | 3.5 3.5
| 2 | two | 2.5 2.5
| 10 | two abc | 2.5 2.5
| 1 | one | 1.5 1.5
| 9 | one abc | 1.5 1.5
+----+-------------------+
13 rows in set (0.00 sec)