简体   繁体   中英

Elastic .Nest Equivelent of field_value_factor

I need to revise a method that builds a SearchDescriptor using .Nest so that the score is higher for product search results for items having a contract price (value of zero).

I captured the serialized version of the query added "field_value_factor" to return the results in the desired order. I have not determined how to achieve this in the .Nest query statement.

Can someone recommend how to revise the .NEST client statements to produce the same search descriptor?

Thank you

Below is the query we want to achieve where you will see field_value_factor at the bottom:

 {
      "from": 0,
  "size": 3000,
  "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": {
    "function_score": { 
       "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": [
                  "fbb3dd2c-f81c-4ff3-bd5b-9c2cffc51540"
                ]
              }
            }
          ]
        }
      },
            "field_value_factor": {
                "field": "priceStatus",
                "factor": -1,
                "modifier": "none"
            }
        }
    }
}

Below is the current method that builds the SearchDescriptor:

private SearchDescriptor<SearchItem> BuildSearchDescriptor(
        string searchTerm,
        IList<Guid> catalogIds,
        int from,
        int size,
        string index,
        string preference,
        int attrSize,
        int valueSize,
        Dictionary<string, string[]> filterProps,
        Dictionary<string, string[]> filterAttrs,
        Guid? categoryId)
    {
        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);

        // Debug the raw string that will post to the ES servers i.e. use this in postman
        //var str = System.Text.Encoding.UTF8.GetString(client.Serializer.Serialize(searchDescriptor));

        return searchDescriptor;
    }

Your JSON query isn't valid; field_value_factor is a function of a function_score query. In NEST 1.x, this would look like

var response = client.Search<Document>(x => x
    .Query(q => q
        .FunctionScore(fs => fs
            .Functions(fu => fu
                .FieldValueFactor(fvf => fvf
                    .Field(f => f.PriceStatus)
                    .Factor(-1)
                    .Modifier(FieldValueFactorModifier.None)
                )
            )
        )
    )
);

public class Document
{
    public string Title { get; set; }

    public int PriceStatus { get; set; }
}

which produces the query

{
  "query": {
    "function_score": {
      "functions": [
        {
          "field_value_factor": {
            "field": "PriceStatus",
            "factor": -1.0,
            "modifier": "none"
          }
        }
      ]
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM