Build NEST SearchDescriptor with Boost for Contract Price

Hello,

I am tasked with an enhancement to a product search. The technology stack is NEST version 1.0.0.0 integrated with Visual Studio 2017 and running Elastic version 2.0. Sorry so old!

I've been asked to ensure that items are ranked higher if they have a contract price (long value of 0 (on contract) or 1 (off contract).

I found great resources referencing boosting score by Popularity. I'd like to revise our NEST SearchDescription query to boost our score for items giving a higher score to those items having a contract price equal to zero.

I am looking for help in revising the NEST query to add a boost value for items having contract price. Below is the our SearchDescriptor query:

var searchDescriptor = new SearchDescriptor<SearchItem>()
                .From(from)
                .Size(size)
                .Query(q =>
                    q.Filtered(fd => BuildFilterTerms(fd, filterProps, filterAttrs, catalogIds, categoryId)
                        .Query(iq => BuildQueryContainer(iq, searchTerm))
                    )
                )
                .Index(index)
                .Preference(preference)
                .Aggregations(agg => BuildAggregationDescriptor(agg, attrSize, valueSize, catalogIds.Count))                
                .Sort(sort => sort.OnField("_score").Descending())
                .SortAscending(p=> p.PriceStatus)
                .SortAscending(p => p.UnitPrice);

When I attempt to use query_score directly into the search query below, I see that this function is not supported for filtered queries. I would really like to apply the boost using NEST.

Can anyone provide a resource or example that I can build upon?

There is more to building the final NEST query that I've not included (but will be happy to if needed). Below is the resulting search descriptor:

{
  "from": 0,
  "size": 50,
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "priceStatus": {
        "order": "asc"
      }
    },
    {
      "unitPrice": {
        "order": "asc"
      }
    }
  ],
  "aggs": {
    "PriceStatus": {
      "terms": {
        "field": "priceStatus",
        "size": 5
      }
    },
    "VendorName": {
      "terms": {
        "field": "vendorName",
        "size": 5
      }
    },
    "CatalogName": {
      "terms": {
        "field": "catalogName",
        "size": 5
      }
    },
    "ManufacturerName": {
      "terms": {
        "field": "manufacturerName",
        "size": 5
      }
    },
    "IsGreen": {
      "terms": {
        "field": "isGreen",
        "size": 5
      }
    },
    "IsValuePack": {
      "terms": {
        "field": "isValuePack",
        "size": 5
      }
    },
    "UnitOfMeasure": {
      "terms": {
        "field": "unitOfMeasure",
        "size": 5
      }
    },
    "Attributes": {
      "nested": {
        "path": "attributes"
      },
      "aggs": {
        "TheAttributeName": {
          "terms": {
            "field": "attributes.name",
            "size": 10
          },
          "aggs": {
            "TheAttributeValue": {
              "terms": {
                "field": "attributes.value",
                "size": 5
              }
            }
          }
        }
      }
    }
  },
  "query": {
    "filtered": {
      "query": {
        "bool": {
          "should": [
            {
              "multi_match": {
                "type": "phrase",
                "query": "pen",
                "slop": 3,
                "boost": 16.0,
                "fields": [
                  "itemNumber*^4",
                  "shortDescription*^4",
                  "subCategory1Name*^1.5",
                  "subCategory2Name*^2.0",
                  "categoryName*^0.9",
                  "longDescription*^0.6",
                  "catalogName*^0.30",
                  "manufactureName*^0.20",
                  "vendorName*^0.15",
                  "upcCode*^0.10"
                ]
              }
            },
            {
              "multi_match": {
                "query": "pen",
                "boost": 15.0,
                "minimum_should_match": "75%",
                "fields": [
                  "itemNumber*^4",
                  "shortDescription*^4",
                  "subCategory1Name*^1.5",
                  "subCategory2Name*^2.0",
                  "categoryName*^0.9",
                  "longDescription*^0.6",
                  "catalogName*^0.30",
                  "manufactureName*^0.20",
                  "vendorName*^0.15",
                  "upcCode*^0.10"
                ]
              }
            },
            {
              "multi_match": {
                "query": "pen",
                "fuzziness": 1.0,
                "slop": 2,
                "minimum_should_match": "75%",
                "fields": [
                  "itemNumber*^4",
                  "shortDescription*^4",
                  "subCategory1Name*^1.5",
                  "subCategory2Name*^2.0",
                  "categoryName*^0.9",
                  "longDescription*^0.6",
                  "catalogName*^0.30",
                  "manufactureName*^0.20",
                  "vendorName*^0.15",
                  "upcCode*^0.10"
                ]
              }
            }
          ]
        }
      },
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "catalogId": [
                  "abb3dc2c-f81c-4gg9-bd5b-9c2cffc51540"
                ]
              }
            }
          ]
        }
      }
    }
  }
} 

The first thing I would absolutely recommend doing if you're targeting Elasticsearch 2.x is to upgrade NEST to the latest 2.x version.

NEST 1.x is incompatible and not supported with Elasticsearch 2.x and whilst it may work for the most part, there are known breaking changes between the Elasticsearch major versions that the 1.x client will not know how to handle.

It sounds like building a bool query that includes a term query in the should clauses that applies a boost for a match on contract prices with value of 0 should do it.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.