ElasticSearch检索--数组、坐标范围、脚本排序、聚合

文章介绍了如何在ElasticSearch中使用嵌套数据类型进行数组查询,包括布尔查询、地理位置范围检索(半径、坐标范围、多边形)以及脚本排序和聚合功能的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ElasticSearch检索

数组

查询只要满足数组中一条数据的结果

采用nested 数据类型

{
    "dynamic": "false",
    "properties": {
        "projectTypeList": {
            "properties": {
                "id": {
                    "type": "integer"
                },
                "level": {
                    "type": "byte"
                },
                "name": {
                    "type": "keyword"
                },
                "order": {
                    "type": "integer"
                },
                "parentId": {
                    "type": "integer"
                }
            }
        },
        "projectStateList": {
            "type": "nested",
            "properties": {
                "boardId": {
                    "type": "integer"
                },
                "boardName": {
                    "type": "keyword"
                },
                "ownerId": {
                    "type": "keyword"
                },
                "ebid": {
                    "type": "keyword"
                },
                "version": {
                    "type": "keyword"
                }
            }
        }
    }
}
            if (CollectionUtils.isNotEmpty(bo.getProjectStateList())) {
                BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
                for (Integer projectState : bo.getProjectStateList()) {
                    BoolQueryBuilder temp = QueryBuilders.boolQuery();
                    NestedQueryBuilder nestedQuery = QueryBuilders
                            .nestedQuery("projectStateList", temp, ScoreMode.None);
                    QueryBuilder projectStateQueryBuilder = QueryBuilders
                            .termQuery("projectStateList.boardId", projectState);
                    temp.must(projectStateQueryBuilder);
                    if (StringUtils.isNotBlank(bo.getOwnerId())) {
                        QueryBuilder ownerIdQueryBuilder = QueryBuilders
                                .termQuery("projectStateList.ownerId", bo.getOwnerId());
                        temp.must(ownerIdQueryBuilder);
                    }
                    if (StringUtils.isNotBlank(bo.getEbid())) {
                        QueryBuilder ebidQueryBuilder = QueryBuilders
                                .termQuery("projectStateList.ebid", bo.getEbid());
                        temp.must(ebidQueryBuilder);
                    }
                    queryBuilder.should(nestedQuery);
                }
                boolQueryBuilder.must(queryBuilder);
            } else {
                BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
                BoolQueryBuilder temp = QueryBuilders.boolQuery();
                NestedQueryBuilder nestedQuery = QueryBuilders
                        .nestedQuery("projectStateList", temp, ScoreMode.None);
                if (StringUtils.isNotBlank(bo.getOwnerId())) {
                    QueryBuilder ownerIdQueryBuilder = QueryBuilders
                            .termQuery("projectStateList.ownerId", bo.getOwnerId());
                    temp.must(ownerIdQueryBuilder);
                }
                if (StringUtils.isNotBlank(bo.getEbid())) {
                    QueryBuilder ebidQueryBuilder = QueryBuilders
                            .termQuery("projectStateList.ebid", bo.getEbid());
                    temp.must(ebidQueryBuilder);
                }
                queryBuilder.should(nestedQuery);
                boolQueryBuilder.must(queryBuilder);
            }

坐标,经纬度

范围检索:1、半径检索;2、坐标范围检索;3、四至
location : lat + “,” + lng

{
    "dynamic": "false",
    "properties": {
        "lat": {
            "type": "float"
        },
        "lng": {
            "type": "float"
        },
        "location": {
            "type": "geo_point"
        }
    }
}
        // 左上右下坐标
        if (StringUtils.isNoneBlank(bo.getMaxLat(), bo.getMaxLng(), bo.getMinLat(),
                bo.getMinLng())) {
            GeoBoundingBoxQueryBuilder locationBoxQueryBuilder = QueryBuilders
                    .geoBoundingBoxQuery("location")
                    .setCornersOGC(new GeoPoint(bo.getMinLat() + "," + bo.getMinLng()),
                            new GeoPoint(bo.getMaxLat() + "," + bo.getMaxLng()));
            boolQueryBuilder.filter(locationBoxQueryBuilder);
        }

        // 半径
        if (StringUtils.isNoneBlank(bo.getCenterX(), bo.getCenterY(), bo.getTargetDistance())) {
            GeoDistanceQueryBuilder locationDistanceQueryBuilder = QueryBuilders
                    .geoDistanceQuery("location")
                    .point(new GeoPoint(bo.getCenterY() + "," + bo.getCenterX()))
                    .distance(bo.getTargetDistance(), DistanceUnit.METERS);
            boolQueryBuilder.filter(locationDistanceQueryBuilder);
        }

        // 多边形
        if (StringUtils.isNotBlank(bo.getFScope())) {
            List<GeoPoint> points = Arrays.asList(StringUtils.split(bo.getFScope(), "|")).stream()
                    .map(p -> new GeoPoint(StringUtils.substringAfter(p, ",") + ","
                            + StringUtils.substringBefore(p, ",")))
                    .collect(Collectors.toList());

            GeoPolygonQueryBuilder locationPolygonQueryBuilder = QueryBuilders
                    .geoPolygonQuery("location", points);
            boolQueryBuilder.filter(locationPolygonQueryBuilder);
        }

ScriptSort 脚本排序

		 String content="if (doc['cityId'].value == "+"'"+bo.getCityIdOrder()+"') {return 0; } else { return 1; }";
            ScriptSortBuilder scriptSortBuilder = new ScriptSortBuilder(
                    new Script(
                            ScriptType.INLINE, // 脚本类型
                            Script.DEFAULT_SCRIPT_LANG, // 脚本语言
                            content, // 脚本内容
                            Collections.emptyMap() // 这里没有用到脚本参数,所以传递一个空map
                    ),
                    ScriptSortBuilder.ScriptSortType.NUMBER // 脚本返回的类型是数值
            ).order(SortOrder.ASC);
            sourceBuilder.sort(scriptSortBuilder);

Aggregation 聚合

            // nest 数组字段聚合
            sourceBuilder.aggregation(
                    AggregationBuilders.nested("boardCount", "boradInfoDocList")
                            .subAggregation(AggregationBuilders.terms("by_ebid").size(500)
                                    .field("boradInfoDocList.ebid")
                                    .subAggregation(AggregationBuilders.terms("by_boardId")
                                            .size(500).field("boradInfoDocList.boardId")
                                            .subAggregation(AggregationBuilders
                                                    .topHits("comareaName").size(1)
                                                    .fetchSource("comareaName", null)))));

            //普通字段聚合
            sourceBuilder.aggregation(AggregationBuilders.terms("districtId")
                        .field("districtId").size(500).subAggregation(AggregationBuilders
                            .topHits("districtName").size(1).fetchSource("districtName", null)));
            
            // 字段求平均
            sourceBuilder.aggregation(AggregationBuilders.avg("avgRent").field("avgRent"));
### 在Elasticsearch中执行坐标计算 对于地理空间数据的操作,Elasticsearch提供了丰富的功能来处理地理位置信息。当涉及到网格点坐标的远场计算时,可以利用`geo_shape`类型的字段来进行复杂的几何运算[^1]。 为了实现特定于z坐标的网格点处的远场计算,在索引文档之前应该先定义好映射结构。如果目标是对三维地理坐标(经度、纬度以及高度或深度)做操作,则可以在创建索引的时候指定包含三个维度的数据模型: ```json PUT /my_geo_index { "mappings": { "properties": { "location": { "type": "geo_point" }, "altitude": { "type": "float" } } } } ``` 上述例子展示了如何设置一个既支持二维地理坐标又额外记录海拔高度的信息模式。然而需要注意的是,标准版Elasticsearch中的`geo_point`并不直接支持真正的三维查询;因此对于涉及Z轴方向上的距离测量或其他形式的空间关系判断可能需要自定义脚本或者借助其他工具完成。 一旦建立了合适的索引并导入了带有位置属性的数据集之后,就可以通过编写Search API请求来进行各种基于地理位置的检索聚合分析工作。例如要查找位于某个圆形区域内的所有地点,并按照它们离中心的距离排序: ```json GET /_search { "query": { "bool": { "must": [ { "match_all": {} } ], "filter": [ { "geo_distance": { "distance": "200km", "location": { "lat": 40, "lon": -70 } } } ] } }, "_source": ["name", "location"], "sort": [ { "_geo_distance": { "location": { "lat": 40, "lon": -70 }, "order": "asc", "unit": "km", "distance_type": "plane" } } ] } ``` 此JSON片段说明了一个典型的搜索命令,它会返回给定半径范围内按直线距离升序排列的结果列表。但是请注意这仅适用于平面直角坐标系下的近似估算而非精确球面三角法求解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值