Reputation: 2232
I just started exploring elasticsearch. I need to find an approach for specifying custom scores at field level. For example:
I have a collection named blog whose documents have following format:
{
"_id": "1736hst26672829",
"name": "Learning regular expressions basics",
"author": "John Lee",
"summery": "Here is summery.",
"body": "Content of the blog."
}
If I search a text 'xyz' in the collection then the result should reflect following score criteria
I need top 10 results on the basis of the above criteria.
:
Upvotes: 1
Views: 827
Reputation: 2379
Scoring in ElasticSearch is extremely customizable, the following applies to query time based custom scoring. There are various other scoring options, by index, in your mapping (and thus applied to every query), on Filters or Facets, using boosts or custom scoring.
While Custom Score Query is generally the most powerful solution, here are the docs for various custom scoring methods to read up on.
The following is probably the simplest methods to apply custom scoring in query time, although I suggest you read up on Custom Score Query.
"query": {
"filtered": {
"query":
"bool": {
"must": [
{"multi_match": {
"fields": [
"name^4",
"author^3",
"summery^2",
"body^1"
],
"query": "xyz",
"operator": "AND",
"type": "cross_fields",
"analyzer": "standard"
}}
]
}
}
}
}
For people who search this answer but wish to use NEST, bellow is the same query using NEST. Use the ^ character to boost specific fields or use OnFieldsWithBoost to give fields custom scoring, and the query is sorted by score.
var query = "xyz";
//Add your field names to a string in lower camelCase as is ES default.
List<string> searchIn = new List<string(new string[] {"_id","name","author","summery","body"});
.Type("blogType")
.SortDescending("_score")
.Query(
q => q.MultiMatch(
t => t.OnFields(
searchIn
.Select(qs => qs == "name" ? "name^4" : qs)
.Select(qs => qs == "author" ? "author^3" : qs)
.Select(qs => qs == "summery" ? "summery^2" : qs)
.Select(qs => qs == "body" ? "body" : qs)
)
.Query(query)
)
)
If you have the correct (default) mapping in ES (C# Object to ES indexed JSON Object), you can also use the following within the OnFields:
t => t.OnFieldsWithBoost(qs => qs.Add(entry => entry.Name, 4.0)
.Add(entry => entry.Author, 3.0)
.Add(entry => entry.Summary, 2.0)
.Add(entry => entry.Body, 1.0))
Upvotes: 2