Elasticsearch NEST 2如何正确映射和使用嵌套类和批量索引

时间:2016-03-31 10:14:20

标签: elasticsearch nested nest

我有三个主要问题需要帮助回答。

  1. 如何正确映射和存储嵌套地图?
  2. 如何搜索文档的嵌套部分?
  3. 你如何批量索引?
  4. 我使用的是Nest版本2,并且一直在查看可以找到Here的新文档。该文档在创建代码的某些部分时非常有用,但遗憾的是它们并没有解释它们如何组合在一起。

    以下是我试图映射的课程。

    [ElasticsearchType(Name = "elasticsearchproduct", IdProperty = "ID")]
    public class esProduct
    {
        public int ID { get; set; }
        [Nested]
        public List<PriceList> PriceList { get; set; }
    }
    
    [ElasticsearchType(Name = "PriceList")]
    public class PriceList
    {
        public int ID { get; set; }
        public decimal Price { get; set; }
    }
    

    和我的映射代码

    var node = new Uri(HOST);
            var settings = new ConnectionSettings(node).DefaultIndex("my-application");
    
            var client = new ElasticClient(settings);
            var map = new CreateIndexDescriptor("my-application")
                            .Mappings(ms => ms
                                .Map<esProduct>(m => m
                                    .AutoMap()
                                    .Properties(ps => ps
                                        .Nested<PriceList>(n => n
                                            .Name(c => c.PriceList)
                                            .AutoMap()
                                        )
                                    )
                                )
                            );
    
            var response = client.Index(map);
    

    这是我得到的回复:

    Valid NEST response built from a succesful low level call on POST: /my-application/createindexdescriptor
    

    所以这似乎有效。下一个指数。

    foreach (DataRow dr in ProductTest.Tables[0].Rows)
    {
        int id = Convert.ToInt32(dr["ID"].ToString());
        List<PriceList> PriceList = new List<PriceList>();
        DataRow[] resultPrice = ProductPriceTest.Tables[0].Select("ID = " + id);
    
        foreach (DataRow drPrice in resultPrice)
        {
            PriceList.Add(new PriceList
            {
                ID = Convert.ToInt32(drPrice["ID"].ToString()),
                Price = Convert.ToDecimal(drPrice["Price"].ToString())    
            }
    
            esProduct product = new esProduct
            {
                ProductDetailID = id,
                PriceList = PriceList
            };
    
           var updateResponse = client.Update<esProduct>(DocumentPath<esProduct>.Id(id), descriptor => descriptor
                                        .Doc(product)
                                        .RetryOnConflict(3)
                                        .Refresh()
                    );
    
           var index = client.Index(product);
        }
    }
    

    这似乎也有效,但是当我来搜索它似乎确实按预期工作。

    var searchResults = client.Search<esProduct>(s => s
                                .From(0)
                                .Size(10)
                                    .Query(q => q
                                           .Nested(n => n
                                               .Path(p => p.PriceList)
                                                .Query(qq => qq
                                                    .Term(t => t.PriceList.First().Price, 100)
                                                    )
                                                )
                                          ));
    

    确实会返回结果,但我期待

    .Term(t => t.PriceList.First().Price, 100)
    

    看起来像

    .Term(t => t.Price, 100)
    

    并且知道正在搜索嵌套的PriceList类,这不是这种情况吗?

    在新版本2的文档中,我找不到批量索引部分。我尝试使用此代码

    var descriptor = new BulkDescriptor();
    
    ***Inside foreach loop***
    
    descriptor.Index<esProduct>(op => op
                                .Document(product)
                                .Id(id)
                                );
    ***Outside foreach loop***
    
    var result = client.Bulk(descriptor);
    

    确实会返回成功回复但是当我搜索时我没有得到任何结果。

    任何帮助都将不胜感激。

    更新

    经过对@Russ的更多调查建议我认为错误必须是我对带有嵌套对象的类的批量索引。

    当我使用

    var index = client.Index(product);
    

    索引我可以使用的每件商品

    var searchResults = client.Search<esProduct>(s => s
                        .From(0)
                        .Size(10)
                            .Query(q => q
                            .Nested(n => n
                                .Path(p => p.PriceList)
                                .Query(qq => qq
                                        .Term(t => t.PriceList.First().Price, 100)
                                    )
                                )
                            )
                         );
    

    搜索并返回结果,但是当我对其进行批量索引时,这不再有效,但是

    var searchResults = client.Search<esProduct>(s => s
                        .From(0)
                        .Size(10)
                        .Query(q => q
                                .Term(t => t.PriceList.First().Price, 100)
                              )
                         );
    

    将起作用,代码b不会对单个索引方法起作用。有谁知道为什么会这样?

    更新2

    从@Russ建议我看一下映射。

    我用来索引的代码是

    var map = new CreateIndexDescriptor(defaultIndex)
                            .Mappings(ms => ms
                                .Map<esProduct>(m => m
                                    .AutoMap()
                                    .Properties(ps => ps
                                        .Nested<PriceList>(n => n
                                            .Name(c => c.PriceList)
                                            .AutoMap()
                                        )
                                    )
                                )
                            );
    
            var response = client.Index(map);
    

    哪个是发布

    http://HOST/fresh-application2/createindexdescriptor {"mappings":{"elasticsearchproduct":{"properties":{"ID":{"type":"integer"},"priceList":{"type":"nested","properties":{"ID":{"type":"integer"},"Price":{"type":"double"}}}}}}}
    

    并致电http://HOST/fresh-application2/_all/_mapping?pretty我正在

    {
      "fresh-application2" : {
        "mappings" : {
          "createindexdescriptor" : {
            "properties" : {
              "mappings" : {
                "properties" : {
                  "elasticsearchproduct" : {
                    "properties" : {
                      "properties" : {
                        "properties" : {
                          "priceList" : {
                            "properties" : {
                              "properties" : {
                                "properties" : {
                                  "ID" : {
                                    "properties" : {
                                      "type" : {
                                        "type" : "string"
                                      }
                                    }
                                  },
                                  "Price" : {
                                    "properties" : {
                                      "type" : {
                                        "type" : "string"
                                      }
                                    }
                                  }
                                }
                              },
                              "type" : {
                                "type" : "string"
                              }
                            }
                          },
                          "ID" : {
                            "properties" : {
                              "type" : {
                                "type" : "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    

    fresh-application2返回的映射根本没有提到嵌套类型,我猜是这个问题。

    我的工作嵌套查询的映射看起来更像是

    {
      "my-application2" : {
        "mappings" : {
          "elasticsearchproduct" : {
            "properties" : {
              "priceList" : {
                "type" : "nested",
                "properties" : {
                  "ID" : {
                    "type" : "integer"
                  },
                  "Price" : {
                    "type" : "double"
                  }
                }
              },
              "ID" : {
                "type" : "integer"
              },
            }
          }
        }
      }
    }
    

    这返回了嵌套类型。我认为那个没有作为类型嵌套返回的是当我开始使用.AutoMap()时,我是否正确使用它?

    更新

    我修复了我的映射问题。我已将映射代码更改为

    var responseMap = client.Map<esProduct>(ms => ms
                                .AutoMap()
                                .Properties(ps => ps
                                    .Nested<PriceList>(n => n
                                        .Name(c => c.PriceList)
                                    .AutoMap()
                                    )
                                )
                            );
    

1 个答案:

答案 0 :(得分:2)

在您正在开发I would recommend logging out requests and responses to Elasticsearch时,您可以看到使用NEST时发送的内容;这样可以更容易地与主要的Elasticsearch文档相关联,并确保请求和响应的主体符合您的期望(例如,对映射,查询等有用)。

你看起来很好的映射,虽然你可以放弃属性,因为你使用流畅的映射;将它们放在那里没有坏处,但它们在很大程度上是多余的(esProduct的类型名称是唯一适用的部分)在这种情况下,因为.Properties()将覆盖应用的推断或基于属性的映射来自.AutoMap()

在您的索引编辑部分中,您更新 esProduct,然后在此之后立即索引同一文档;我不确定这里的目的是什么,但 update 电话对我来说是多余的; index 调用将在 update 之后直接覆盖索引中具有给定id的文档(并且在刷新间隔后将在搜索结果中可见)。 更新上的.RetryOnConflict(3)将使用optimistic concurrency control执行更新(实际上是获取然后索引操作在集群内部的文档中,如果文档版本在 get index 之间发生变化,则会尝试3次。如果您使用更新替换整个文档,即不是部分更新,则不一定需要重新尝试冲突(并且按照之前的说明,由于 index 调用将覆盖索引中具有给定id的文档,因此在您的示例中更新调用看起来完全不必要了。

nested query看起来正确;您指定嵌套类型的路径,然后对嵌套类型的字段的查询也将包括路径。I'll update the NEST nested query usage documentation to better demonstrate

批量通话看起来很好;您可能希望批量发送文档,例如批量索引一次500个文档,如果需要索引很多文档。一次批量呼叫发送的数量取决于多种因素,包括文档大小,分析方式,群集性能等,因此需要进行试验以获得适合您情况的大批量呼叫。

我会检查以确保您正在使用正确的索引,索引包含您期望的文档计数,并找到您知道PriceList.Price为100的文档,并查看索引的内容为了它。在你开始跑步的时候使用Sense执行此操作可能会更快。