azureazure-cognitive-searchazure-search-.net-sdk

Applying boost terms to Searches


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
}

Solution

  • 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);
    
    

    Output