【问题标题】:Elasticsearch .net Client Nest querycontainer always nullElasticsearch .net 客户端嵌套查询容器始终为空
【发布时间】:2016-04-17 12:24:51
【问题描述】:

尝试通过构建一个始终为空的查询容器来动态过滤函数中的结果。我不明白为什么,因为当我调试时,我看到函数中填充了 q 变量,但是当我检查它的值时,它总是为空。示例代码如下。你知道我做错了什么吗?

谢谢。

QueryContainer q = null;

        if (!ProductType.HasValue || (ProductType.HasValue && ProductType.Value == B2CVariables.PRODUCTTYPE_PRODUCT))
        {
            q = Query<ProductModel>.Term(t => t.Field(u => u.ProductTypeID == B2CVariables.PRODUCTTYPE_PRODUCT));
            q &= Query<ProductModel>.Term(t => t.Field(u => u.Stocks.Any() ? u.Stocks.Any(z => z.StatusID == B2CVariables.STATUS_PRODUCT_ONLINE && (!z.CheckStockStatus || (z.CheckStockStatus && z.CurrentStockCount > 0))) : false));
        }

【问题讨论】:

    标签: asp.net asp.net-mvc elasticsearch nest


    【解决方案1】:

    查询的构造不正确according to the signature of a Term query constructed with the static Query&lt;T&gt; type。

    Field(Func&lt;T, object&gt;) 是一个强类型表达式,用于获取查询应操作的字段,并且应使用.Value(object value) 指定该字段必须与术语查询匹配的值。这是假设以下设置的示例

    public static class B2CVariables
    {
        public const int PRODUCTTYPE_PRODUCT = 2;
    
        public const int STATUS_PRODUCT_ONLINE = 1;
    }
    
    public class ProductModel
    {
        public IList<Stock> Stocks { get; set;}
    
        public int ProductTypeID { get; set;}
    }
    
    public class Stock
    {
        public int StatusID { get; set;}
    
        public bool CheckStockStatus { get; set;}
    
        public int CurrentStockCount { get; set;}
    }
    

    查询

    if (!ProductType.HasValue || (ProductType.HasValue && ProductType.Value == B2CVariables.PRODUCTTYPE_PRODUCT))
    {
        q = Query<ProductModel>.Term(t => t
                .Field(u => u.ProductTypeID)
                .Value(B2CVariables.PRODUCTTYPE_PRODUCT));
    
        q &= Query<ProductModel>.Term(t => t
                 .Field(u => u.Stocks.First().StatusID)
                 .Value(B2CVariables.STATUS_PRODUCT_ONLINE)) && 
             (Query<ProductModel>.Term(t => t
                  .Field(u => u.Stocks.First().CheckStockStatus)
                  .Value(false)) ||          
             (Query<ProductModel>.Term(t => t
                 .Field(u => u.Stocks.First().CheckStockStatus)
                 .Value(true)) && 
              Query<ProductModel>.Range(t => t
                  .Field(u => u.Stocks.First().CurrentStockCount)
                  .GreaterThan(0))));
    }
    

    u.Stocks.First().StatusID 是一个表达式,用于获取ProductModel 上子对象的状态ID;我们使用.First() 的事实并不意味着我们要求first status id,它只是一个表达式,它决定了如何以简洁的方式访问 status id。有关详细信息,请参阅field inference 部分。

    因为Query&lt;T&gt;.Term(t =&gt; t.Field(u =&gt; u.Field).Value(value)) 在组合许多查询时会变得冗长,所以可以使用简写Query&lt;T&gt;.Term(t =&gt; t.Field, value) 代替(实际上它更短,即使由于缩进在此示例中看起来几乎相同) !)

    if (!ProductType.HasValue || (ProductType.HasValue && ProductType.Value == B2CVariables.PRODUCTTYPE_PRODUCT))
    {
        q = Query<ProductModel>.Term(
                t => t.ProductTypeID, 
                B2CVariables.PRODUCTTYPE_PRODUCT);
    
        q &= Query<ProductModel>.Term(
                 t => t.Stocks.First().StatusID, 
                 B2CVariables.STATUS_PRODUCT_ONLINE) && 
             (Query<ProductModel>.Term(
                 t => t.Stocks.First().CheckStockStatus, 
                 false) ||       
             (Query<ProductModel>.Term(
                 t => t.Stocks.First().CheckStockStatus, 
                 true) && 
              Query<ProductModel>.Range(t => t
                  .Field(u => u.Stocks.First().CurrentStockCount)
                  .GreaterThan(0))));
    }
    

    两者都产生以下查询

    {
      "bool": {
        "must": [
          {
            "term": {
              "productTypeID": {
                "value": 2
              }
            }
          },
          {
            "term": {
              "stocks.statusID": {
                "value": 1
              }
            }
          },
          {
            "bool": {
              "should": [
                {
                  "term": {
                    "stocks.checkStockStatus": {
                      "value": false
                    }
                  }
                },
                {
                  "bool": {
                    "must": [
                      {
                        "term": {
                          "stocks.checkStockStatus": {
                            "value": true
                          }
                        }
                      },
                      {
                        "range": {
                          "stocks.currentStockCount": {
                            "gt": 0.0
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    }
    

    然而,这个查询可能不会做你想做的事;因为有一个 bool 查询组合了跨子对象的两个查询(checkStockStatus 上的 term 查询和 currentStockcount 上的 range),the Stock object should be modelled as a nested object 使得两个查询的匹配项必须来自相同的股票对象。

    一旦建模为嵌套对象,查询将变为

    int? ProductType = 2;
    QueryContainer q = null;
    
    if (!ProductType.HasValue || (ProductType.HasValue && ProductType.Value == B2CVariables.PRODUCTTYPE_PRODUCT))
    {
        q = Query<ProductModel>.Term(t => t
            .Field(u => u.ProductTypeID)
            .Value(B2CVariables.PRODUCTTYPE_PRODUCT));
    
        q &= Query<ProductModel>.Nested(n => n
                .Path(u => u.Stocks.First())
                .Query(nq => nq
                    .Term(t => t
                        .Field(u => u.Stocks.First().StatusID)
                        .Value(B2CVariables.STATUS_PRODUCT_ONLINE)) &&
    
                    (nq.Term(t => t
                        .Field(u => u.Stocks.First().CheckStockStatus)
                        .Value(false)) ||
                    (nq.Term(t => t
                        .Field(u => u.Stocks.First().CheckStockStatus)
                        .Value(true)
                    ) && nq.Range(t => t
                        .Field(u => u.Stocks.First().CurrentStockCount)
                        .GreaterThan(0)
                    )))
                )
            );
    }
    

    使用查询 json

    {
      "bool": {
        "must": [
          {
            "term": {
              "productTypeID": {
                "value": 2
              }
            }
          },
          {
            "nested": {
              "query": {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "stocks.statusID": {
                          "value": 1
                        }
                      }
                    },
                    {
                      "bool": {
                        "should": [
                          {
                            "term": {
                              "stocks.checkStockStatus": {
                                "value": false
                              }
                            }
                          },
                          {
                            "bool": {
                              "must": [
                                {
                                  "term": {
                                    "stocks.checkStockStatus": {
                                      "value": true
                                    }
                                  }
                                },
                                {
                                  "range": {
                                    "stocks.currentStockCount": {
                                      "gt": 0.0
                                    }
                                  }
                                }
                              ]
                            }
                          }
                        ]
                      }
                    }
                  ]
                }
              },
              "path": "stocks"
            }
          }
        ]
      }
    }
    

    【讨论】:

    • 嗨,Russ,我用您提供的最后一个代码更改了代码,它会生成与您所说的相同的查询,但它不能以某种方式工作。当我检查数据时,它应该至少返回 1018 个结果,但它根本不返回任何内容。我不熟悉弹性搜索查询结构,所以我不明白出了什么问题。那么,我现在可以尝试什么来找出问题所在?
    • 您是否将stocks 映射为nested 类型?如果它不是 nested 类型,它将不起作用。您可能需要使用将stocks 映射为nested 类型的新映射将数据重新索引到新索引中
    • 我要试试,现在我还有一个问题。我有一个名为 categoryids 的 guid 属性。它包含产品的类别 ID。让我们说 1,2 作为简化它的值。我想查询一个值列表以匹配其中至少一个。我的意思是,例如,我将传递 1,3,4 进行搜索,它应该返回具有 1 或 3 或 4(至少其中之一)的产品应该在 categoryids 值中。我也应该将 categoryids 属性映射为嵌套吗?我该如何查询?谢谢。
    • 您应该真的将其作为一个单独的问题提出:) 不,您不需要将其映射为nested; nested 类型确实适用于您希望跨 nested 类型的属性执行复合查询时。 guid 只有一个属性,即 guid 值本身,您可以查询,因此 categoryIds 不应映射为 nested。您可能希望将其映射为 not_analyzed,因为您可能会对它们进行结构化查询(例如 term 查询)。
    • 你能帮我处理一下stackoverflow.com/questions/36697563/…>吗?
    猜你喜欢
    • 2014-09-02
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多