所有,我正在使用NEST来使用ElasticSearch 6.x,为简单起见,我根据此处提供的NEST 6.x文档https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/parent-child-relationships.html创建了以下POCO设置的映射 . 我的数据模型很简单

  • 客户

  • 订单

  • 包裹

  • OrderItem

这是C#POCO设置

[ElasticsearchType(Name = "customer")]
public class Customer 
{
    [PropertyName("customerId")]
    public int CustomerId { get; set; }

    [PropertyName("firstName")]
    [Text]
    public string FirstName { get; set; }

    [PropertyName("lastName")]
    [Text]
    public string LastName { get; set; }

    [PropertyName("email")]
    [Keyword]
    public string Email { get; set; }
    [PropertyName("customer_join_field")]
    public JoinField CustomerJoinField { get; set; }
}

    [ElasticsearchType(Name = "order")]
    public class Order : Customer
    {
        [PropertyName("orderId")]
        public int OrderId { get; set; }        

        [PropertyName("orderAmount")]
        public decimal Amount { get; set; }

        [Nested]
        [PropertyName("packages")]
        public List<Package> Packages { get; set; }

        [Nested]
        [PropertyName("orderItems")]
        public List<OrderItem> OrderItems { get; set; }

    }

    public class Package
    {
        public int PackageId { get; set; }
        public int Qty { get; set; }
        public int OrderId { get; set; }
        public string Weight { get; set; }
    }

    public class OrderItem
    {
        public int OrderItemId { get; set; }
        public int Quantity { get; set; }
        public decimal UnitPrice { get; set; }
    }

构建ES客户端

public static ElasticClient ESClient
    {
        get
        {

            var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
            var settings = new ConnectionSettings(connectionPool)
                                          .DefaultMappingFor<Customer>(i => i
                                          .IndexName("fa")
                                          .TypeName("customer"))
                                          .DefaultMappingFor<Order>(i => i
                                          .IndexName("fa")
                                          .TypeName("customer"))                                              
                                          .EnableDebugMode()
                                          .PrettyJson()
                                          .RequestTimeout(TimeSpan.FromMinutes(2));

            return new ElasticClient(settings);
        }
    }

配置索引(fa)

public static void ConfigureIndex()
{
    try
    {
        var createIndexResponse = ESClient.CreateIndex("fa", c => c
             .Index<Customer>()
             .Mappings(ms => ms
             .Map<Customer>(m => m
             .RoutingField(r => r.Required())
             .AutoMap<Customer>()
             .AutoMap<Order>()
             .Properties(props => props
                .Join(j => j
                    .Name(p => p.CustomerJoinField)
                    .Relations(r => r
                        .Join<Customer, Order>()
                        )
                    )
                 )
              )
          )
     );

    }

添加客户和订单类型(在相同的客户类型下,因为索引在ES 6.x中只能有一种类型)

public static void AddCustomerDocument(Customer cust)
    {
        try
        {
            var result = ESClient.Index<Customer>(cust,
                 c => c
                 .Id(cust.CustomerId)//to avaoid random Ids
                 .Routing(cust.CustomerId)
                );

            //var response = ESClient.Index(cust, i => i.Routing(Routing.From(cust)));
        }
        catch (Exception ex)
        {

            throw;
        }
    }   



public static void AddOrderDocument(Order order)
    {
        try
        {


            var result = ESClient.Index<Customer>(order,
                 c => c
                 .Id(order.OrderId)//to avaoid random Ids
                 .Routing(order.CustomerId)
                );

            //var response = ESClient.IndexDocument<Order>(order);
        }
        catch (Exception ex)
        {

            throw;
        }
    }

ES中生成的映射是

{
    "fa": {
        "mappings": {
            "customer": {
                "_routing": {
                    "required": true
                },
                "properties": {
                    "customerId": {
                        "type": "integer"
                    },
                    "customer_join_field": {
                        "type": "join",
                        "eager_global_ordinals": true,
                        "relations": {
                            "customer": "order"
                        }
                    },
                    "email": {
                        "type": "keyword"
                    },
                    "firstName": {
                        "type": "text"
                    },
                    "lastName": {
                        "type": "text"
                    },
                    "orderAmount": {
                        "type": "double"
                    },
                    "orderId": {
                        "type": "integer"
                    },
                    "orderItems": {
                        "type": "nested",
                        "properties": {
                            "orderItemId": {
                                "type": "integer"
                            },
                            "quantity": {
                                "type": "integer"
                            },
                            "unitPrice": {
                                "type": "double"
                            }
                        }
                    },
                    "packages": {
                        "type": "nested",
                        "properties": {
                            "orderId": {
                                "type": "integer"
                            },
                            "packageId": {
                                "type": "integer"
                            },
                            "qty": {
                                "type": "integer"
                            },
                            "weight": {
                                "type": "text",
                                "fields": {
                                    "keyword": {
                                        "type": "keyword",
                                        "ignore_above": 256
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

我正在查询此索引,以使用unitprice 12.23获取特定客户(CustomerId = 1)下的特定orderItem .

这是我的查询DSL

{

    "query":{

        "parent_id":{
            "type":"order",
            "id":"1"
        },
            "nested":{
            "path":"orderItems",
            "score_mode":"avg",
            "query":{
                "bool":{
                    "must":[
                          {"match":{"orderItems.unitPrice" : "12.23"}}
                        ]
                }
            }
        }
    }
}

当我这样做时,我收到以下的错误消息

{
    "error": {
        "root_cause": [
            {
                "type": "parsing_exception",
                "reason": "[parent_id] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
                "line": 9,
                "col": 4
            }
        ],
        "type": "parsing_exception",
        "reason": "[parent_id] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
        "line": 9,
        "col": 4
    },
    "status": 400
}

我的问题是

  • 是否可以(或推荐)在ES 6.x中同时执行父子关系和嵌套类型?

  • 如果没有,我的选项是否仅限于对模型进行非规范化(包,OrderItems是Customer的子项,而不是Order和OrderItems中的Order和添加字段?)或者对ES进行多次查询并移动扁平化数据的逻辑格式我想申请方?

这是我创建的示例数据(localhost:9200 / fa / customer / _search)

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 3,
        "max_score": 1,
        "hits": [
            {
                "_index": "fa",
                "_type": "customer",
                "_id": "1",
                "_score": 1,
                "_routing": "1",
                "_source": {
                    "customerId": 1,
                    "firstName": "Rennish",
                    "lastName": "Joseph",
                    "email": "rennish@yahoo.com",
                    "customer_join_field": "customer"
                }
            },
            {
                "_index": "fa",
                "_type": "customer",
                "_id": "100",
                "_score": 1,
                "_routing": "1",
                "_source": {
                    "orderId": 100,
                    "orderAmount": 23.45,
                    "packages": [
                        {
                            "packageId": 1,
                            "qty": 2,
                            "orderId": 1,
                            "weight": "2.3"
                        },
                        {
                            "packageId": 2,
                            "qty": 1,
                            "orderId": 1,
                            "weight": "2.5"
                        }
                    ],
                    "orderItems": [
                        {
                            "orderItemId": 1,
                            "quantity": 2,
                            "unitPrice": 12.23
                        },
                        {
                            "orderItemId": 2,
                            "quantity": 1,
                            "unitPrice": 10.23
                        }
                    ],
                    "customerId": 1,
                    "customer_join_field": {
                        "name": "order",
                        "parent": "1"
                    }
                }
            },
            {
                "_index": "fa",
                "_type": "customer",
                "_id": "101",
                "_score": 1,
                "_routing": "1",
                "_source": {
                    "orderId": 101,
                    "orderAmount": 23.45,
                    "packages": [
                        {
                            "packageId": 1,
                            "qty": 2,
                            "orderId": 1,
                            "weight": "2.3"
                        },
                        {
                            "packageId": 2,
                            "qty": 1,
                            "orderId": 1,
                            "weight": "2.5"
                        }
                    ],
                    "orderItems": [
                        {
                            "orderItemId": 1,
                            "quantity": 2,
                            "unitPrice": 12.23
                        },
                        {
                            "orderItemId": 2,
                            "quantity": 1,
                            "unitPrice": 10.23
                        }
                    ],
                    "customerId": 1,
                    "customer_join_field": {
                        "name": "order",
                        "parent": "1"
                    }
                }
            }
        ]
    }
}