【问题标题】:Conditional Sorting on 2 fields in Elastic Search NestElastic Search Nest 中 2 个字段的条件排序
【发布时间】:2016-10-26 07:39:16
【问题描述】:

我输入了我的数据,如果 type 是 A 然后我需要按 price1 排序 如果 type 是 B 那么我需要按 price2 排序,

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

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

【问题讨论】:

  • elasticsearch索引有两种类型?
  • 我有一个“列表类型”字段,可以是A也可以是B。
  • 您可以分享您的索引映射和示例文档吗?

标签: c# elasticsearch nest


【解决方案1】:

您正在寻找类似的东西吗?

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

【讨论】:

    【解决方案2】:

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

     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。我确实认为这有点“hacky”,但希望有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      • 1970-01-01
      • 2021-01-17
      相关资源
      最近更新 更多