ES 嵌套查询

背景

一个配方由多种原材料组成,需求是根据各种原材料的用量搜索出对应的配方

配方实体类

class Formula {

    private long id;

    private String name;

    private List<Material> materials;

}

class Material {

    @JsonProperty("material_id")
    private long materialId;

    private float amount;

}

1、定义索引映射 Mapping

PUT /formula
{
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "name": {
        "type": "text"
      },
      "materials": {
        "type": "nested",
        "properties": {
          "material_id": {
            "type": "long"
          },
          "amount": {
            "type": "float"
          }
        }
      }
    }
  }
}

2、添加测试数据

POST /formula/_doc/1
{
  "id": "1",
  "name": "formula A",
  "materials": [
    { "material_id": "material_1", "amount": 100 },
    { "material_id": "material_2", "amount": 50 }
  ]
}

POST /formula/_doc/2
{
  "id": "2",
  "name": "formula B",
  "materials": [
    { "material_id": "material_2", "amount": 30 },
    { "material_id": "material_3", "amount": 20 }
  ]
}

3、查询

GET /formula/_search
{
  "query": {
    "bool": {
        "must": [
            {
                "match": {
                    "name": "formula A"
                }
            },
            {
                "nested": {
                    "path": "materials",
                    "query": {
                        "bool": {
                        "must": [
                            { "match": { "materials.material_id": "2" } },
                            { "range": { "materials.amount": { "gte": 40, "lte": 60 } } }
                        ]
                        }
                    }
                }
            }
        ]
    }
  }
}

RestHighLevelClient

// nested
BoolQueryBuilder nestedBoolQueryBuilder = new BoolQueryBuilder();
nestedBoolQueryBuilder.must().add(QueryBuilders.matchPhraseQuery("materials.material_id", 1));
nestedBoolQueryBuilder.must().add(QueryBuilders.rangeQuery("materials.amount").from(40).to(60));
NestedQueryBuilder nestedQueryBuilder =  QueryBuilders.nestedQuery("materials", nestedBoolQueryBuilder, ScoreMode.Avg);

// query
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(nestedQueryBuilder);
// simple
boolQueryBuilder.must(QueryBuilders.matchQuery("name", "formula A"));

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(boolQueryBuilder);

SearchRequest searchRequest = new SearchRequest(new String[]{index}, searchSourceBuilder);

// response
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

ElasticsearchClient

SearchResponse<Formula> response = elasticsearchClient.search(s -> s
                .index("formula")
                .query(q -> q.match(t -> t.field("name").query("formula A")))
                .query(q -> q.nested(nq -> nq.path("materials")
                                .query(nq1 -> nq1.match(t -> t.field("materials.material_id").query("2")))
                                .query(nq2 -> nq2.range(r -> r.field("materials.amount").from("40").to("60")))
                        )
                ),
        Formula.class
);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值