弹性搜索巢中2个字段的条件排序

本文关键字:字段 条件 排序 2个 搜索 | 更新日期: 2023-09-27 18:14:53

我在我的数据,如果类型类型是A,那么我需要按价格1排序如果type是B,那么我需要按price2,

排序

那么在c#中我们如何编写查询呢?

{
  "test": {
    "mappings": {
      "listings": {
        "properties": {
          "productname": {
            "type": "string"
          },
          "ptype": {
            "type": "string"
          },
          "price1": {
            "type": "float"
          },
          "price2": {
            "type": "float"
          }
        }
      }
    }
  }
}

弹性搜索巢中2个字段的条件排序

你在寻找这样的东西吗?

_elasticClient.SearchAsync<ListingsModel>(s => s
    .Type(type)
    .Sort(o => 
    {
        if(type == "A")
            return o.OnField("price1");
        else
            return o.OnField("price2");
    })
    //rest of query

我能做的最好的事情是这样的

 class Program
    {
        static void Main(string[] args)
        {
            var random = new Random();
            var uri = new Uri("http://localhost.fiddler:9200");
            var indexName = "test_index";
            ElasticClient db = new ElasticClient(uri);
            db.DeleteIndex(indexName);
            foreach (var item in Enumerable.Range(0, 10).Select(i => new A { Price1 = random.NextDouble() * 1000 }))
            {
                db.Index(item, inx => inx.Index(indexName));
            }
            foreach (var item in Enumerable.Range(0, 10).Select(i => new B { Price2 = random.NextDouble() * 1000 }))
            {
                db.Index(item, inx => inx.Index(indexName));
            }
            //db.IndexMany(Enumerable.Range(0, 10).Select(i => new A { Price1 = random.NextDouble() * 1000 }), indexName); When using this got nothing back since the query was too fast after index
            //db.IndexMany(Enumerable.Range(0, 10).Select(i => new B { Price2 = random.NextDouble() * 1000 }), indexName);
            var data = db.Search<JObject>(q =>
                q.Index(indexName)
                .Size(20)
                .Type("")
                .Sort(s => s.Script(scd => scd
                    .Type("number")
                    .Script(sc => sc
                        //.Inline(@" doc['price1']?  doc['price1'] : doc['price2']") if no price1 field in object B then you can use this and no need for TypeIndex
                        .Inline(@"doc['typeIndex'] == 0?  doc['price1'] : doc['price2']")// typeIndex must be a number lucene has no string literal support
                        .Lang("expression")
                        ).Order(SortOrder.Descending))));

            Console.WriteLine("DONE");
            Console.ReadLine();
        }
    }
    [ElasticsearchType(Name="A")]
    public class A 
    {
        [Number]
        public int TypeIndex { get { return 0; } }
        [Number]
        public double Price1 { get; set; }
    }
    [ElasticsearchType(Name = "B")]
    public class B
    {
        [Number]
        public int TypeIndex { get { return 1; } }
        [Number]
        public double Price2 { get; set; }
    }

你可以用groovy来做,但我不知道它会有多好。表达式默认是打开的,它们使用lucene。我确实认为这有点"俗气",但希望会有所帮助。