elasticsearch仅显示嵌套对象没有值的位置

时间:2017-08-21 18:35:38

标签: elasticsearch nest

我有以下结构(简化):

{
    "id": 100,
    "vendorStatuses": [
        {
            "id": 200,
            "status": "Open"
        }
    ]
}

我想要找的是没有供应商状态的记录。我们最近从elasticseach 1.x升级到5.x,但我无法转换为恢复此功能。

我的旧Nest查询如下所示:

!Filter<PurchaseOrder>.Nested(nfd => nfd.Path(x => x.VendorStatuses.First())
    .Filter(f2 => f2.Missing(y => y.Id))); 

新查询(现在Missing不可用)到目前为止看起来像这样:

Query<PurchaseOrder>
    .Bool(z => z
        .MustNot(a => a
            .Exists(t => t
                .Field(f => f.VendorStatuses)
            )
        )
    );

产生这个:

GET purchaseorder/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "vendorStatuses",
          }
        }
      ]
    }
  }
}

但我仍然看到有vendorStatuses条记录的结果。

我做错了什么?我已经尝试搜索vendorStatuses.id或其他字段,但它无效。当我尝试颠倒逻辑并执行must时,我看不到任何结果。我也尝试过这样做nested,但无法与之相提并论。

2 个答案:

答案 0 :(得分:1)

使用must_notexists的查询不是像{x}查询那样的nested查询。我想你正在寻找像

这样的东西
var query = Query<PurchaseOrder>
    .Bool(z => z
        .MustNot(a => a
            .Nested(n => n
                .Path(p => p.VendorStatuses)
                .Query(nq => nq
                    .Exists(t => t
                        .Field(f => f.VendorStatuses)
                    )
                )
            )
        )
    );

client.Search<PurchaseOrder>(s => s.Query(_ => query));

产生

{
  "query": {
    "bool": {
      "must_not": [
        {
          "nested": {
            "query": {
              "exists": {
                "field": "vendorStatuses"
              }
            },
            "path": "vendorStatuses"
          }
        }
      ]
    }
  }
}

您可以使用operator overloading使查询更简洁

var query = !Query<PurchaseOrder>
    .Nested(n => n
        .Path(p => p.VendorStatuses)
        .Query(nq => nq
            .Exists(t => t
                .Field(f => f.VendorStatuses)
            )
        )
    );

答案 1 :(得分:0)

在我看来,我发现了一种远非理想的解决方法。我在我的PurchaseOrder模型上为NumberOfStatuses创建了一个新属性,然后我只对0的值进行了术语搜索。

public int NumberOfStatuses => VendorStatuses.OrEmptyIfNull().Count();

Query<PurchaseOrder>.Term(t => t.Field(po => po.NumberOfStatuses).Value(0));