ES地理查询实例

建库

示例

schema

DELETE yg_data

PUT yg_data
{
  "mappings": {
    "properties": {
      "filePaht": {
        "type": "text"
      },
      "fileName": {
        "type": "text"
      },
      "labels": {
        "type": "text"
      },
      "satellite": {
        "type": "keyword"
      },
      "sensor": {
        "type": "keyword"
      },
      "acquisitionTime": {
        "type": "date",
        "format": "yyyy-MM-dd"
      },
      "cloudiness": {
        "type": "text"
      },
      "resoltion": {
        "type": "text"
      },
      "trackNum": {
        "type": "integer"
      },
      "path_": {
        "type": "integer"
      },
      "row_": {
        "type": "integer"
      },
      "ltLon": {
        "type": "float"
      },
      "ltLat": {
        "type": "float"
      },
      "rtLon": {
        "type": "float"
      },
      "rtLat": {
        "type": "float"
      },
      "rbLon": {
        "type": "float"
      },
      "rbLat": {
        "type": "float"
      },
      "lbLon": {
        "type": "float"
      },
      "geoLocation": {
        "type": "geo_shape"
      }
    }
  }
}


PUT /yg_data/_doc/1
{
  "filePath": "",
  "fileName": "1",
  "labels": [
    "自然保护区",
    "道路"
  ],
  "satellite": "GF6",
  "sensor": "PMS",
  "acquisitionTime": "2020-02-20",
  "cloudiness": "15.3%",
  "resolution": "2M",
  "trackNum": 9267,
  "path_": 598,
  "row_": 73,
  "ltLon": 35.556927,
  "ltLat": 119.490336,
  "rtLon": 35.365411,
  "rtLat": 120.517026,
  "rbLon": 34.575652,
  "rbLat": 120.292628,
  "lbLon": 34.766248,
  "lbLat": 119.275608,
  "geoLocation": {
    "type": "polygon",
    "coordinates": [
      [
        [
          35.556927,
          119.490336
        ],
        [
          35.365411,
          120.517026
        ],
        [
          34.575652,
          120.292628
        ],
        [
          34.766248,
          119.275608
        ],
        [
          35.556927,
          119.490336
        ]
      ]
    ]
  }
}

PUT /yg_data/_doc/2
{
  "filePath": "",
  "fileName": "2",
  "labels": [
    "自然保护区",
    "交通"
  ],
  "satellite": "GF6",
  "sensor": "PMS",
  "acquisitionTime": "2020-02-18",
  "cloudiness": "15.3%",
  "resolution": "2M",
  "trackNum": 9267,
  "path_": 598,
  "row_": 73,
  "ltLon": 38.926269,
  "ltLat": 117.466326,
  "rtLon": 38.789251,
  "rtLat": 118.215529,
  "rbLon": 38.195255,
  "rbLat": 118.035474,
  "lbLon": 38.331646,
  "lbLat": 117.292403,
  "geoLocation": {
    "type": "polygon",
    "coordinates": [
      [
        [
          38.926269,
          117.466326
        ],
        [
          38.789251,
          118.215529
        ],
        [
          38.195255,
          118.035474
        ],
        [
          38.331646,
          117.292403
        ],
        [
          38.926269,
          117.466326
        ]
      ]
    ]
  }
}

PUT /yg_data/_doc/3
{
  "labels": [
    "海域"
  ]
}

PUT /yg_data/_doc/4
{
  "labels": [
    "公路"
  ]
}

PUT /yg_data/_doc/5
{
  "labels": [
    "交通"
  ]
}

PUT /yg_data/_doc/6
{
  "labels": [
    "森林"
  ]
}

PUT /yg_data/_doc/7
{
  "labels": [
    "自然保护区",
    "公路",
    "道路"
  ]
}

说明
  • geoLocation
    geo_shape字段, 由图片四个角坐标确定,用于在查询时判定图片是否在地域边界内。

查询测试

  • 查询包含自然标签的文档
GET /yg_data/_search
{
  "query": {
    "multi_match": {
      "query": "自然",
      "fields": ["labels"]
    }
  }
}
  • 查询日期在2020-02-192020-02-21之间的文档。
    注意这里对格式有明确要求, 2月必须写成02,而不能只写2
GET /yg_data/_search
{
  "query": {
    "range": {
      "acquisitionTime": {
        "gte": "2020-02-19",
        "lte": "2020-02-21",
        "format": "yyyy-MM-dd"
      }
    }
  }
}
  • 查询包含自然标签且与给定范围有交集的文档
GET /yg_data/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "labels": "自然"
          }
        },
        {
          "geo_shape": {
            "geoLocation": {
              "shape": {
                "type": "polygon",
                "coordinates": [
                  [ [119.9, 35.0], [121, 35], [121, 36], [119.9, 36], [119.9, 35.0] ]
                ]
              },
              "relation": "intersects"
            }
          }
        },
        {
          "range": {
            "acquisitionTime": {
              "gte": "2020-02-19",
              "lte": "2020-02-21",
              "format": "yyyy-MM-dd"
            }
          }
        }
      ]
    }
  }
}
  • 这个例子演示了多个地域限制时的查询方法
GET /yg_data/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "labels": "自然"
          }
        },
        {
          "bool": {
            "should": [
              {
                "geo_shape": {
                  "geoLocation": {
                    "shape": {
                      "type": "polygon",
                      "coordinates": [
                        [ [119.9, 35.0], [121, 35], [121, 36], [119.9, 36], [119.9, 35.0] ]
                      ]
                    },
                    "relation": "intersects"
                  }
                }
              },
              {
                "geo_shape": {
                  "geoLocation": {
                    "shape": {
                      "type": "polygon",
                      "coordinates": [
                        [ [119.9, 35.0], [121, 35], [121, 36], [119.9, 36], [119.9, 35.0] ]
                      ]
                    },
                    "relation": "intersects"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}
  • 查找filename[1,2,3]中,且label路况相关的文档
GET /yg_data/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "labels": "路况"
          }
        },
        {
          "terms": {
            "filename": [1, 2, 7]
          }
        }
      ]
    }
  }
}

java中的查询方式

/**
 * 用户语句查询 分页检索ES
 * @param label 标签信息
 * @param picPlaces 地点信息
 * @param picTimeSt 时间信息
 * @param picTimeEd 时间信息
 * @param pageNo 分页 当前页面
 * @param pageSize 分页 页面大小
 * @return ES检索图片文档信息
 * @throws IOException QueryBuilders.geoShapeQuery 可能引发polygon不合法异常
 */
public PagePictureDoc getImgsByContentWithESQuery(String label, List<String> picPlaces, String picTimeSt,
                                                  String picTimeEd, int pageNo, int pageSize) throws IOException {
    // label match 按照ES中的labels字段与用户查询的label匹配
    MatchQueryBuilder labelQuery = QueryBuilders.matchQuery("labels", label);

    // location match 按照ES中的geoLocation字段与地区边界进行交集匹配
    BoolQueryBuilder geoQuery = QueryBuilders.boolQuery();
    // 判空
    if (!picPlaces.isEmpty()) {
        // place to city boundary 获取地区的经纬度边界
        List<CityBoundary> cityBoundaries = place2cityBoundary(picPlaces);
        for (CityBoundary boundary : cityBoundaries) {
            // 地区的边界
            for (String bound : boundary.getPolygon().split("#")) {
                CoordinatesBuilder poly = new CoordinatesBuilder();
                for (String geo : bound.split(";")){
                    String[] latlng = geo.split(",");
                    poly = poly.coordinate(Double.parseDouble(latlng[1]), Double.parseDouble(latlng[0]));
                }
                // ES与地区边界的匹配查询
                geoQuery = geoQuery.should(QueryBuilders.geoShapeQuery("geoLocation", new PolygonBuilder(poly))
                        .relation(ShapeRelation.INTERSECTS));
            }
        }
    }


    // time match ES的acquisitionTime字段按照yyyy-MM-dd格式与用户查询的时间字段匹配
    RangeQueryBuilder timeQuery = QueryBuilders.rangeQuery("acquisitionTime").format("yyyy-MM-dd")
            // true表示包括边界 在from中是下界,在to中是上界
            .from(picTimeSt, true)
            .to(picTimeEd, true);

    // query
    boolean queryFlag = false;
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    if (label != null && !"".equals(label)) {
        boolQueryBuilder = boolQueryBuilder.must(labelQuery);
        queryFlag = true;
    }
    if (picTimeSt != null && !"".equals(picTimeSt)) {
        boolQueryBuilder = boolQueryBuilder.must(timeQuery);
        queryFlag = true;
    }
    if (picPlaces != null && !picPlaces.isEmpty()) {
        boolQueryBuilder = boolQueryBuilder.must(geoQuery);
        queryFlag = true;
    }

    // 是否为有效查询
    if (queryFlag) {
        return contextRepo.getContextSearchPictures(boolQueryBuilder, pageNo, pageSize);
    } else {
        return null;
    }
}
public class ContextRepo {

    /**
     * @param query 查询语句翻译后得到的ES检索(DSL)语句
     * @param pageNo 分页 当前页面
     * @param pageSize 分页 页面大小
     * @return 分页对象 ES检索图片文档信息
     */
    public List<SearchHit> getContextSearchPictures(QueryBuilder query, int pageNo, int pageSize) {
        if (pageNo < 1) {
            pageNo = 1;
        }
        if (pageSize < 0) {
            pageSize = globalConfig.pageSize;
        }
        int from = (pageNo-1) * pageSize;
        Client client = getClient();
        SearchResponse response = client.prepareSearch()
                .setFrom(from)
                .setSize(pageSize)
                .setQuery(query)
                .execute()
                .actionGet();
        // 将搜索结果封装到ItemBaseDoc持久化对象
        List<SearchHit> searchHits = Arrays.asList(response.getHits().getHits());
        int totalSize = response.getHits().getTotalHits().value;

        return searchHits;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值