NEST API GeoShapes字段的默认值 [英] NEST API Default value for GeoShapes fields

查看:49
本文介绍了NEST API GeoShapes字段的默认值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

但是,如果缺少 geometry 字段,Elasticsearch会引发异常.

无论如何,通过在映射中使用默认值(空值)或任何其他方式来避免这种情况.

解决方案

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

理想地,应以防止最终用户提供无效值的方式约束提供给索引形状的值.如果那不可行,则可以在 indexName exists 查询和 ids 查询的过滤子句的 bool 查询>索引,然后将索引形状的几何形状查询过滤器添加到搜索请求中.

例如

 私有静态void Main(){var documentIndex =文件";varshapesIndex ="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);如果(client.Indices.Exists(documentsIndex).Exists)client.Indices.Delete(documentsIndex);client.Indices.Create(documentsIndex,c => c.Map< Document>(m => m.AutoMap()));如果(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 [] {新文件{ID = 1LocalityId = 1,LocationShape = GeoWKTReader.Read("POLYGON((30 20,20 15,20 25,30 20))")},新文件{ID = 2LocalityId = 2},}).IndexMany(new []{新形状{ID = 1几何= 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尺寸(0)查询(q => + q.Ids(i => i.Values(shapeId))&&+ q.Exists(e => e.Field("geometry"))));Func< QueryContainerDescriptor< Document>,QueryContainer>geoShapeQuery = q =>q;如果(searchResponse.Total == 1)geoShapeQuery = q =>+ q.GeoShape(g => g.Field("locationShape").Relation(GeoShapeRelation.Inner).IndexedShape(f => f.Id(shapeId).Index(shapesIndex).Path("geometry")));client.Search< Document>(s => s查询(q => + q.Term(t => t.Field(f => f.LocalityId)值(2))||geoShapeQuery(q)));}公共课文件{public int ID {get;放;}public int LocalityId {get;放;}公开IGeoShape LocationShape {get;放;}}公共课形{public int ID {get;放;}公开IGeoShape几何{放;}} 

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

We are using a filter as per following:

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")
        )
    )
);

However, if the geometry field is missing, Elasticsearch throws an exception.

Is there anyway to avoid this by using a default (Null Value) in the mapping or any other way.

解决方案

It is not possible to avoid the exception in this case. Elasticsearch assumes that the parameters that the user provides to a pre-indexed shape are valid.

Ideally, the values supplied to the indexed shape should be constrained in a manner that prevents an end user from supplying invalid values. If that is unfeasible, you could run a bool query with filter clauses of exists query and ids query on the indexName index before adding the indexed shape geoshape query filter to the search request.

For example

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; }
}

If var shapeId = 1; is changed to var shapeId = 2; then the geoshape query is not added to the filter clauses when searching on the documents index.

这篇关于NEST API GeoShapes字段的默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆