NEST API GeoShapes 字段的默认值

NEST API Default value for GeoShapes fields

我们正在使用如下过滤器:

filters.Add(fq => fq
    .Term(t => t
        .Field(f => f.LocalityId)
        .Value(locationParams[2])) || fq
    .GeoShape(g => g
        .Field("locationShape")
        .Relation(GeoShapeRelation.Within)
        .IndexedShape(f => f
            .Id(searchCriteria.spLocationId)
            .Index(indexName)
            .Path("geometry")
        )
    )
);

但是,如果缺少 geometry 字段,Elasticsearch 会抛出异常。

是否可以通过在映射中使用默认值(空值)或任何其他方式来避免这种情况。

在这种情况下无法避免异常。 Elasticsearch 假定用户提供给预索引形状的参数是有效的。

理想情况下,应以防止最终用户提供无效值的方式限制提供给索引形状的值。如果这不可行,您可以在添加索引形状 geoshape 之前 运行 一个 bool 查询,其中包含 exists 查询的过滤子句和 ids 查询 indexName 索引搜索请求的查询过滤器。

例如

private static void Main()
{
    var documentsIndex = "documents";
    var shapesIndex = "shapes";
    var host = "localhost";
    var pool = new SingleNodeConnectionPool(new Uri($"http://{host}:9200"));

    var settings = new ConnectionSettings(pool)
        .DefaultMappingFor<Document>(m => m.IndexName(documentsIndex))
        .DefaultMappingFor<Shape>(m => m.IndexName(shapesIndex));

    var client = new ElasticClient(settings);

    if (client.Indices.Exists(documentsIndex).Exists)
        client.Indices.Delete(documentsIndex);

    client.Indices.Create(documentsIndex, c => c
        .Map<Document>(m => m
            .AutoMap()
        )
    );

    if (client.Indices.Exists(shapesIndex).Exists)
        client.Indices.Delete(shapesIndex);

    client.Indices.Create(shapesIndex, c => c
        .Map<Shape>(m => m
            .AutoMap()
        )
    );

    client.Bulk(b => b
        .IndexMany(new [] { 
            new Document 
            {
                Id = 1,
                LocalityId = 1,
                LocationShape = GeoWKTReader.Read("POLYGON ((30 20, 20 15, 20 25, 30 20))")
            },
            new Document
            {
                Id = 2,
                LocalityId = 2
            },
        })
        .IndexMany(new [] 
        {
            new Shape 
            {
                Id = 1,
                Geometry = GeoWKTReader.Read("POLYGON ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35))")
            }
        })
        .Refresh(Refresh.WaitFor)
    );

    var shapeId = 1;

    var searchResponse = client.Search<Shape>(s => s
        .Size(0)
        .Query(q => +q
            .Ids(i => i.Values(shapeId)) && +q
            .Exists(e => e.Field("geometry"))
        )
    );

    Func<QueryContainerDescriptor<Document>, QueryContainer> geoShapeQuery = q => q;

    if (searchResponse.Total == 1)
        geoShapeQuery = q => +q
            .GeoShape(g => g
                .Field("locationShape")
                .Relation(GeoShapeRelation.Within)
                .IndexedShape(f => f
                    .Id(shapeId)
                    .Index(shapesIndex)
                    .Path("geometry")
                )
            );

    client.Search<Document>(s => s
        .Query(q => +q
            .Term(t => t
                .Field(f => f.LocalityId)
                .Value(2)
            ) || geoShapeQuery(q)
        )
    );
}

public class Document
{
    public int Id { get; set; }
    public int LocalityId { get; set; }
    public IGeoShape LocationShape { get; set; }
}

public class Shape
{
    public int Id { get; set; }
    public IGeoShape Geometry { get; set; }
}

如果 var shapeId = 1; 更改为 var shapeId = 2;,则在搜索文档索引时不会将 geoshape 查询添加到过滤器子句。