为何Elasticsearch相同形状的geo_shape查询contains与within结果不同?
当使用与文档中完全相同的Geo-Shape进行查询时,within匹配成功但contains无结果,核心原因在于Elasticsearch对这两种空间关系的严格定义差异,以及底层遵循的OGC空间关系规范(DE-9IM模型)。
具体原因
Elasticsearch的geo_shape查询空间关系基于OGC简单特征规范中的定义,结合DE-9IM(Dimensionally Extended 9-Intersection Model)模型判断:
1. within的判断逻辑
within要求文档形状的所有点都位于查询形状的内部或边界上,且两者的交集完全等于文档形状。当两个形状完全相同时,文档形状的每一个点都落在查询形状的范围内,完全满足within的条件,因此会返回匹配结果。
2. contains的判断逻辑
contains要求查询形状的所有点都位于文档形状的内部或边界上,同时文档形状必须存在至少一个点不在查询形状的范围内(即文档形状是查询形状的真超集)。当两个形状完全相同时,文档形状没有任何点超出查询形状,不满足“真超集”的要求,因此contains不会返回结果。
简单总结:
A within B:A是B的子集(包含两者完全相等的情况)A contains B:B是A的真子集(A必须严格大于/包含B)
验证示例
如果修改查询形状,让它成为文档形状的真子集(比如缩小矩形范围),contains就会返回结果:
POST /example/_search { "query": { "geo_shape": { "location": { "shape": { "type": "polygon", "coordinates": [ [ [-1.0, 52.0], [-1.0, 51.9], [0.0, 51.9], [0.0, 52.0], [-1.0, 52.0] ] ] }, "relation": "contains" } } } }
此时查询形状完全落在文档形状内部,且文档形状存在超出查询形状的区域,contains会成功匹配原文档。
补充说明
如果需要匹配“两个形状完全相同”的场景,可以使用intersects关系(只要形状有交集就匹配,完全相同属于交集的极端情况);若需严格校验形状一致,可在within匹配后额外校验形状的坐标、面积等参数。
内容的提问来源于stack exchange,提问作者Valentin Popa

