I have been trying to apply category boosting to my searches but having trouble with making the boosting optional. I have category filtering setup using the "filter" property.
Filtering is done like this where ids from one group need to match once.
Categories/any(c: c/Id eq 'group1-id1' or c/Id eq 'group1-id2') and Categories/any(c: c/Id eq 'group2-id1')
The problem is i want to boost a separate id we can call this "boosted-id" which is optional but should return this result at the top of the list. I've tried a few different ways but can't get this to play nicely with or without a search term.
Applies the correct boost score but only results with boosted-id return
{
"search": "Categories/Id:boosted-id^20",
"filter": "...example filter from above",
"searchMode": "all",
"queryType": "full",
}
Applies the correct boost score but only results with boosted-id
{
"search": "Categories/Id:boosted-id^20 or *",
"filter": "...example filter from above",
"searchMode": "all",
"queryType": "full",
}
Updating the filter using search.ismatchscoring will act as an AND filter im not sure how to update this to work as a boost and you cant apply a specific boost score to ismatchscoring so i'm not sure how affective it can be.
{
"search": "Categories/Id:boosted-id^20 or *",
"filter": "(Categories/any(c: c/Id eq 'category-id-1') and search.ismatchscoring('boosted-id', 'Categories/Id')",
"searchMode": "all",
"queryType": "full",
}
This is what i currently have it works even though ismatchscoring is only for filtering but if i wanted to only boost the featured category it won't work and im 99% sure this is the incorrect way of boosting and happens to work.
{
"search": "search.ismatchscoring('categorygroup1-id1', 'Categories.Id') OR search.ismatchscoring('categorygroup1-id2', 'Categories.Id') OR search.ismatchscoring('categorygroup2-id1', 'Categories.Id') OR search.ismatchscoring('categorygroup2-id2', 'Categories.Id') OR search.ismatchscoring('boosted-id', 'Categories.Id')",
"searchMode": "any",
"queryType": "full",
"filter": "(Categories/any(category: category/Id eq 'categorygroup1-id1' or category/Id eq 'categorygroup1-id2')) and (Categories/any(category: category/Id eq 'categorygroup2-id1' or category/Id eq 'categorygroup2-id2')))",
"count": true
}
Use search.ismatchscoring
to boost boostedid
AND combine it with your other filters.
{
"search": "*",
"searchMode": "any",
"queryType": "full",
"filter": "(Categories/any(c: c/Id eq 'categorygroup1id1' or c/Id eq 'categorygroup1id2')) and (Categories/any(c: c/Id eq 'categorygroup2id1' or c/Id eq 'categorygroup2id2'))",
"scoringProfile": "boost-profile",
"scoringParameters": [
"boostedCategory=boostedid"
],
"count": true
}
Define in your Index like this:
{
"name": "boostprofile",
"functions": [
{
"type": "magnitude",
"fieldName": "Categories/Id",
"boost": 20,
"interpolation": "linear",
"parameters": {
"boostingRangeStart": 0,
"boostingRangeEnd": 1,
"constantBoostBeyondRange": true
}
}
],
"functionAggregation": "sum"
}
Use search.ismatchscoring
like this if you don't want a scoring profile:
{
"search": "search.ismatchscoring('boosted-id', 'Categories.Id') OR *",
"filter": "(Categories/any(c: c/Id eq 'categorygroup1-id1' or c/Id eq 'categorygroup1-id2')) and (Categories/any(c: c/Id eq 'categorygroup2-id1' or c/Id eq 'categorygroup2-id2'))",
"searchMode": "any",
"queryType": "full",
"count": true
}
var parameters = new SearchOptions
{
Filter = "(Categories/any(c: c/Id eq 'categorygroup1-id1' or c/Id eq 'categorygroup1id2')) and (Categories/any(c: c/Id eq 'categorygroup2id1' or c/Id eq 'categorygroup2id2'))",
SearchMode = SearchMode.Any,
QueryType = SearchQueryType.Full,
ScoringProfile = "boostprofile",
ScoringParameters = { new ScoringParameter("boostedCategory", "boostedid") },
Size = 10,
IncludeTotalCount = true
};
var results = await searchClient.SearchAsync<YourIndexModel>("*", parameters);