Azure 搜索 - GeographyPoint 的查询集合

Azure Search - Query Collection of GeographyPoint

我正在尝试从我的索引中查询给定范围内的集合 GeographyPoint。我正在使用 Azure 搜索。

我的索引包含 GeographyPoint 列表

public class Parent
{
     public List<Child> Coordinates {get; set;}
}


public class Child
{ 
     public GeographyPoint Coordinates { get; set; }
}

我知道索引上是否有一个 属性 命名位置,您可以使用类似以下内容查询它:

$filter=geo.distance(location, geography'POINT(-82.51571 31.89063)') le 0.1524

但是如何查询集合?我试过使用 any/all 过滤器,例如:

$filter=geo.distance(IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates), geography'POINT(-82.51571 31.89063)') le 0.1524

但我得到错误:"Invalid expression: The Any/All query expression must evaluate to a single boolean value.\r\nParameter name: $filter"

如能提供有关如何查询 GeographyPoint 集合的任何帮助,我们将不胜感激。

问题在于您构建过滤器的方式。让我们使用类型对其进行分解,因为这是查看问题出在哪里的最简单方法。

$filter=geo.distance(IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates), geography'POINT(-82.51571 31.89063)') le 0.1524

从外到内,过滤器中最上面的表达式必须是布尔值,并且在此处检查,因为您正在比较 geo.distance(returns Edm.Double ) 使用 le 的文字距离。所以那部分没问题。

接下来,我们来看geo.distance。它需要类型为 Edm.GeographyPoint 和 returns 和 Edm.Double 的两个点。第二个参数是一个字面量点,所以没关系,但第一个参数不是。接下来我们再看看。

此处 geo.distance 的第一个参数是表达式 IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates)。虽然它实际上是一个运算符,但您可以将 any 视为一种 returns 布尔值的函数。那将是一个问题,因为 geo.distance 需要一个点,而不是布尔值。这是我们发现问题所在的第一条线索,但实际上并不能解释您看到的错误消息。让我们进一步深入了解这一点。

暂时假设表达式 IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates) 是您的整个过滤器。您仍然会收到相同的错误消息:"Invalid expression: The Any/All query expression must evaluate to a single boolean value." 要了解原因,请考虑 anyall 对类型的期望。每个都迭代某种类型的集合,将 lambda 表达式形式的谓词应用于每个元素。在这种情况下,lambda 表达式是 c/PhysicalAddress/Coordinates,它(我假设)是一个 Edm.GeographyPoint,而不是布尔值。

退后一步,考虑这里涉及的基数会有所帮助。每个文档都包含一家公司,该公司有许多办公室,每个办公室都有一个地理点位置。我假设目标是匹配整个文档,以防这些坐标中的任何一个与过滤器匹配。在那种情况下,您真的只需要重新排序查询的各个部分,以便类型和基数对齐:

$filter=IndexedCompany/Offices/any(office: geo.distance(office/PhysicalAddress/Coordinates, geography'POINT(-82.51571 31.89063)') le 0.1524)

过滤器仍然是布尔表达式,因为那是 any 的类型。传递给 any 的 lambda 接受一个办公室,将 geo.distance 应用于其地理位置,并将距离与所需值进行比较。现在一切类型检查和迭代发生在正确的地方。

示例:搜索=*

"value": [
    {
        "@search.score": 1,
        "id": "myid1",
        "pts": [
            {
                "type": "Point",
                "coordinates": [ 0, 0 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            },
            {
                "type": "Point",
                "coordinates": [ 0, 1 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            }
        ]
    },
    {
        "@search.score": 1,
        "id": "myid2",
        "pts": [
            {
                "type": "Point",
                "coordinates": [ 0, 10 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            },
            {
                "type": "Point",
                "coordinates": [ 0, 11 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            }
        ]
    }
]

示例 $filter=pts/any(pt: geo.distance(pt, geography'POINT(0 2)') le 111.3192394008)

"value": [
    {
        "@search.score": 1,
        "id": "myid1",
        "pts": [
            {
                "type": "Point",
                "coordinates": [ 0, 0 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            },
            {
                "type": "Point",
                "coordinates": [ 0, 1 ],
                "crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
            }
        ]
    }
]