繁体   English   中英

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

[英]Elasticsearch NEST 2 How to correctly map and use nested classes and bulk index

我需要回答三个主要问题。

  1. 如何正确映射和存储嵌套地图?
  2. 如何搜索文档的嵌套部分?
  3. 您如何批量索引?

我正在使用Nest版本2,并且一直在查看可以在此处找到的新文档。 该文档在创建代码的某些部分时很有用,但不幸的是没有说明它们如何组合在一起。

这是我要映射的课程。

[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的通话中?

{
  "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()
                                )
                            )
                        );

在开发过程中, 我建议注销对Elasticsearch的请求和响应,以便您可以查看使用NEST时发送的内容。 这将使与主要的Elasticsearch文档的联系变得更加容易,并确保请求和响应的主体与您的期望相符(例如,对于映射,查询等有用)。

尽管使用流利的映射可以放弃属性,但您所拥有的映射看起来不错。 在这里放置它们没有什么害处,但是它们在很大程度上是多余的( esProduct的类型名称是唯一适用的部分),因为.Properties()会覆盖从调用.AutoMap()

在索引部分中, 更新 esProduct ,然后紧接着更新 索引 ,再次索引相同的文档; 我不确定这里的意图是什么,但是更新调用对我来说似乎是多余的。 索引调用将在更新后立即覆盖索引中具有给定ID的文档(并且在刷新间隔之后将在搜索结果中可见)。 更新中.RetryOnConflict(3)将使用开放式并发控制来执行更新(实际上是对集群内部文档进行获取然后索引操作,如果文档版本在两次更新之间更改,则尝试3次) getindex )。 如果您要用更新(而不是部分更新)替换整个文档,那么就真的没有必要重试冲突了(并且如前所述,示例中的update调用看起来完全不必要,因为索引调用将覆盖在索引中具有给定ID的文档)。

nested查询看起来正确; 您指定嵌套类型的路径,然后对嵌套类型上的字段的查询也将包括该路径。 我将更新NEST嵌套查询用法文档,以更好地演示

批量调用看起来不错; 您可能需要批量发送文件,例如一次索引500个文件,如果需要对很多文件建立索引。 一个批量调用中发送多少个将取决于许多因素,包括文档大小,如何分析,集群的性能,因此需要进行实验以根据您的情况获得一个好的批量调用。

我将检查以确保您命中了正确的索引,该索引包含了您期望的文档数量,并找到了一个已知的PriceList.Price为100的文档,并查看了为其编制索引的内容。 跑步时,使用Sense进行此操作可能更快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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