ES 嵌套查询

背景

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

配方实体类

java 复制代码
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

java 复制代码
// 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

java 复制代码
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
);
相关推荐
Wils0nEdwards12 小时前
Windows本地 git 版本管理
windows·git·elasticsearch
不吃鱼的羊15 小时前
提交代码添加Change-Id
大数据·elasticsearch·搜索引擎
逸Y 仙X15 小时前
文章四:Elasticsearch 的扩容与集群升级
java·大数据·elasticsearch·搜索引擎·全文检索
逆境不可逃16 小时前
【与我学 ClaudeCode】协作篇 之 Worktree + Task Isolation :目录隔离的并行执行通道
大数据·elasticsearch·搜索引擎
逸Y 仙X17 小时前
Elasticsearch安全集群构建的常见问题
java·大数据·安全·elasticsearch·搜索引擎·全文检索
Lyyaoo.17 小时前
ES快速入门
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客2 天前
一个查询,无限 Elasticsearch Serverless 项目:跨项目搜索介绍
大数据·elasticsearch·搜索引擎·信息可视化·云原生·serverless·全文检索
fengxin_rou2 天前
【SpringBoot+Elasticsearch 内容搜索系统实战】:架构设计与全流程实现
spring boot·后端·elasticsearch
逸Y 仙X2 天前
文章三:Elasticsearch 集群恢复和索引分布
java·大数据·linux·服务器·elasticsearch·搜索引擎·全文检索
INFINI Labs3 天前
Easysearch analysis-ik 多词典性能优化:从性能回退到分词性能提升 25%~30%
elasticsearch·性能优化·分词·performance·easysearch·ik