聚合嵌套 ElasticSearch 中的字典

问题描述

所以我有一组索引产品,其中包含一个带有单个键和一个值列表的字典,我试图用它来构建分面搜索。然而,我是一个非常有弹性的新手。

    Product Product {
    Dictionary<string,List<string>> Properties
    //extra fields removed for simplicity
    }

其中属性可能类似于

["Color":["Blue","Yellow","Red"],"Size":["Small","Medium","Large"] 

["Material":["Wood"],"Shape":["Circle","Square"],"Size":["Tiny","Large","Huge"]

我希望编写一些聚合,它们将返回键以及这些键的值。 即如果上面的例子要被索引,第一个聚合将返回一个包含 "Color","Size","Material","Shape"

的桶

并且第二个聚合将返回 4 个桶,每个桶都有每个键的唯一值。 即Size:["Tiny","small","medium","large","huge"]

我意识到我需要为此进行嵌套聚合,但是我的尝试都没有带回桶中的任何东西。任何指针将不胜感激。这是我目前所拥有的。

    var ProductsQuery = client.Search<Product>(s => s
        .Index("products")
        .Query(q => q.MatchAll())
        .Aggregations(a => a
            .nested("properties",n => n
                .Path(p => p.Properties.Suffix("keyword"))
                    .Aggregations(a => a
                        .Terms("property-keys",t => t
                            .Field(f => f.Properties.Keys.Suffix("keyword"))))));

编辑一些要求的细节:

当前的属性映射(它似乎为每个 Key 创建一个新映射,我不确定这是否是典型的?)我没有把整个对象映射放在这里,因为它相当大。产品有很多字段:

"properties" : {
  "properties" : {
    "Colour" : {
      "type" : "text","fields" : {
        "keyword" : {
          "type" : "keyword","ignore_above" : 256
        }
      }
    },"Equipment" : {
      "type" : "text","Football Age" : {
      "type" : "text","Football Size" : {
      "type" : "text","Frame Weight" : {
      "type" : "text","Garment" : {
      "type" : "text","Head Shape" : {
      "type" : "text","Level" : {
      "type" : "text","Product" : {
      "type" : "text","Size" : {
      "type" : "text","Sport" : {
      "type" : "text","Surface" : {
      "type" : "text","Type" : {
      "type" : "text","Unit" : {
      "type" : "text","Weight" : {
      "type" : "text","comparer" : {
      "type" : "object"
    },"count" : {
      "type" : "integer"
    },"item" : {
      "type" : "text","keys" : {
      "properties" : {
        "count" : {
          "type" : "integer"
        }
      }
    },"values" : {
      "properties" : {
        "count" : {
          "type" : "integer"
        }
      }
    }
  }
}

和一些索引文档

"hits" : [
  {
    "_index" : "products-20-01-2021-13-49-08","_type" : "_doc","_id" : "134550","_score" : 1.0,"_source" : {
      "properties" : {
        "Type" : [
          "Sleds"
        ],"Product" : [
          "Sleds"
        ],"Colour" : [
          "Black"
        ]
      }
    }
  },{
    "_index" : "products-20-01-2021-13-49-08","_id" : "134566","_source" : {
      "properties" : {
        "Sport" : [
          "fitness"
        ],"Type" : [
          "Corner","Edge","Middle"
        ],"Size" : [
          "10mm","15mm","20mm"
        ],"Product" : [
          "Floor Matting"
        ]
      }
    }
  },"_id" : "134576","_source" : {
      "properties" : {
        "Sport" : [
          "Rugby"
        ],"Type" : [
          "Skills Training"
        ],"Equipment" : [
          "Rugby Balls"
        ],"Size" : [
          "4","5"
        ],"Level" : [
          "Skills"
        ]
      }
    }
  },"_id" : "134579","Type" : [
          "Match Union"
        ],"Level" : [
          "Club"," School"
        ],"Unit" : [
          "12 Pack","Each"
        ],"Colour" : [
          "Blue","Red","White"
        ]
      }
    }
  },"_id" : "134600","Size" : [
          "Large","Small","X/Large","X/Small","XX/Small","XXX/Small"
        ],"Garment" : [
          "gloves"
        ],"Colour" : [
          "Red"
        ]
      }
    }
  },"_id" : "134601","_source" : {
      "properties" : {
        "Sport" : [
          "Netball"
        ],"_id" : "134609","Colour" : [
          "Black","Green"
        ]
      }
    }
  },"_id" : "134617","_source" : {
      "properties" : {
        "Sport" : [
          "Football"
        ],"Type" : [
          "Training"
        ],"Football Size" : [
          "2"
        ],"Equipment" : [
          "Footballs"
        ],"Weight" : [
          "290","360"
        ],"Surface" : [
          "Grass"," Astroturf"
        ],"Football Age" : [
          "9-14 years"," 14+ years"
        ]
      }
    }
  },"_id" : "134548","Grey"
        ]
      }
    }
  },"_id" : "134558","_source" : {
      "properties" : {
        "Sport" : [
          "Squash"
        ],"Equipment" : [
          "Squash Rackets"
        ],"Size" : [
          "27\""
        ],"Head Shape" : [
          "Bridged Closed Throat"
        ],"Frame Weight" : [
          "Over 160g"
        ]
      }
    }
  }
]

解决方法

首先,为了获得这些存储桶,您可以使用 Query DSL 说明以下内容:

POST products-*/_search
{
  "size": 0,"aggs": {
    "by_Colour": {
      "terms": {
        "field": "properties.Colour.keyword"
      }
    },"by_Size": {
      "terms": {
        "field": "properties.Size.keyword"
      }
    }
  }
}

然后需要将其翻译成 NEST 代码 -- 我相信那里有很多示例。


但您的观察是正确的——ES 自动创建了大量映射。 我建议不要使用当前的数据格式,而是使用:

{
  "properties": [
    {
      "key": "Type","values": ["Sleds"]
    },{
      "key": "Product",{
      "key": "Colour","values": ["Black"]
    }
  ]
}

并使 properties 类型为 nested

这样您将查询共享路径 properties.key 并在 properties.values.keyword 上聚合。

请记住,nested 字段类型需要它们自己的实际 nested mapping -- 如果没有正确的映射,您将无法使用嵌套查询。

查看此 related questionthis answer 以获取更多上下文。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...