/* SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. * * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ using System; using System.Collections.Generic; using System.Runtime.Serialization; using OpenSearch.Net.Utf8Json; namespace OpenSearch.Client { [InterfaceDataContract] [JsonFormatter(typeof(CompositeFormatter))] public interface IGeoShapeQuery : IFieldNameQuery { /// /// Will ignore an unmapped field and will not match any documents for this query. /// This can be useful when querying multiple indexes which might have different mappings. /// [DataMember(Name ="ignore_unmapped")] bool? IgnoreUnmapped { get; set; } /// /// Indexed geo shape to search with /// [DataMember(Name ="indexed_shape")] IFieldLookup IndexedShape { get; set; } /// /// Controls the spatial relation operator to use at search time. /// [DataMember(Name ="relation")] GeoShapeRelation? Relation { get; set; } /// /// The geo shape to search with /// [DataMember(Name ="shape")] IGeoShape Shape { get; set; } } public class GeoShapeQuery : FieldNameQueryBase, IGeoShapeQuery { /// public bool? IgnoreUnmapped { get; set; } /// public IFieldLookup IndexedShape { get; set; } /// public GeoShapeRelation? Relation { get; set; } /// public IGeoShape Shape { get; set; } protected override bool Conditionless => IsConditionless(this); internal static bool IsConditionless(IGeoShapeQuery q) { if (q.Field.IsConditionless()) return true; switch (q.Shape) { case ICircleGeoShape circleGeoShape: return circleGeoShape.Coordinates == null || string.IsNullOrEmpty(circleGeoShape?.Radius); case IEnvelopeGeoShape envelopeGeoShape: return envelopeGeoShape.Coordinates == null; case IGeometryCollection geometryCollection: return geometryCollection.Geometries == null; case ILineStringGeoShape lineStringGeoShape: return lineStringGeoShape.Coordinates == null; case IMultiLineStringGeoShape multiLineStringGeoShape: return multiLineStringGeoShape.Coordinates == null; case IMultiPointGeoShape multiPointGeoShape: return multiPointGeoShape.Coordinates == null; case IMultiPolygonGeoShape multiPolygonGeoShape: return multiPolygonGeoShape.Coordinates == null; case IPointGeoShape pointGeoShape: return pointGeoShape.Coordinates == null; case IPolygonGeoShape polygonGeoShape: return polygonGeoShape.Coordinates == null; case null: return q.IndexedShape.IsConditionless(); default: return true; } } internal override void InternalWrapInContainer(IQueryContainer container) => container.GeoShape = this; } public class GeoShapeQueryDescriptor : FieldNameQueryDescriptorBase, IGeoShapeQuery, T>, IGeoShapeQuery where T : class { protected override bool Conditionless => GeoShapeQuery.IsConditionless(this); bool? IGeoShapeQuery.IgnoreUnmapped { get; set; } IFieldLookup IGeoShapeQuery.IndexedShape { get; set; } GeoShapeRelation? IGeoShapeQuery.Relation { get; set; } IGeoShape IGeoShapeQuery.Shape { get; set; } /// public GeoShapeQueryDescriptor Relation(GeoShapeRelation? relation) => Assign(relation, (a, v) => a.Relation = v); /// public GeoShapeQueryDescriptor IgnoreUnmapped(bool? ignoreUnmapped = true) => Assign(ignoreUnmapped, (a, v) => a.IgnoreUnmapped = v); /// public GeoShapeQueryDescriptor Shape(Func selector) => Assign(selector, (a, v) => a.Shape = v?.Invoke(new GeoShapeDescriptor())); /// public GeoShapeQueryDescriptor IndexedShape(Func, IFieldLookup> selector) => Assign(selector, (a, v) => a.IndexedShape = v?.Invoke(new FieldLookupDescriptor())); } /// /// Descriptor for building a /// public class GeoShapeDescriptor : DescriptorBase { public IGeoShape Circle(GeoCoordinate coordinate, string radius) => new CircleGeoShape(coordinate, radius); public IGeoShape Envelope(GeoCoordinate topLeftCoordinate, GeoCoordinate bottomRightCoordinate) => new EnvelopeGeoShape(new[] { topLeftCoordinate, bottomRightCoordinate }); public IGeoShape Envelope(IEnumerable coordinates) => new EnvelopeGeoShape(coordinates); public IGeoShape GeometryCollection(IEnumerable geometries) => new GeometryCollection(geometries); public IGeoShape GeometryCollection(params IGeoShape[] geometries) => new GeometryCollection(geometries); public IGeoShape LineString(IEnumerable coordinates) => new LineStringGeoShape(coordinates); public IGeoShape LineString(params GeoCoordinate[] coordinates) => new LineStringGeoShape(coordinates); public IGeoShape MultiLineString(IEnumerable> coordinates) => new MultiLineStringGeoShape(coordinates); public IGeoShape MultiLineString(params IEnumerable[] coordinates) => new MultiLineStringGeoShape(coordinates); public IGeoShape Point(GeoCoordinate coordinates) => new PointGeoShape(coordinates); public IGeoShape MultiPoint(IEnumerable coordinates) => new MultiPointGeoShape(coordinates); public IGeoShape MultiPoint(params GeoCoordinate[] coordinates) => new MultiPointGeoShape(coordinates); public IGeoShape Polygon(IEnumerable> coordinates) => new PolygonGeoShape(coordinates); public IGeoShape Polygon(params IEnumerable[] coordinates) => new PolygonGeoShape(coordinates); public IGeoShape MultiPolygon(IEnumerable>> coordinates) => new MultiPolygonGeoShape(coordinates); public IGeoShape MultiPolygon(params IEnumerable>[] coordinates) => new MultiPolygonGeoShape(coordinates); } }