From ab60fb227bf483c4500db9ca3a2d11b60027e930 Mon Sep 17 00:00:00 2001 From: oneRain Date: Wed, 12 May 2021 13:56:28 +0800 Subject: [PATCH] feat: support geo query --- Storage/Storage.Test/GeoTest.cs | 29 +++++++++++++++++++ .../Query/LCCompositionalCondition.cs | 8 +++++ Storage/Storage/Public/LCQuery.cs | 13 +++++++++ 3 files changed, 50 insertions(+) diff --git a/Storage/Storage.Test/GeoTest.cs b/Storage/Storage.Test/GeoTest.cs index 5efe217..42b5582 100644 --- a/Storage/Storage.Test/GeoTest.cs +++ b/Storage/Storage.Test/GeoTest.cs @@ -1,4 +1,6 @@ using NUnit.Framework; +using System; +using System.Threading.Tasks; using LeanCloud.Storage; namespace Storage.Test { @@ -19,5 +21,32 @@ namespace Storage.Test { TestContext.WriteLine(radians); Assert.Less(radians - 0.0005, 0.0001); } + + [Test] + public async Task Query() { + LCObject geoObj = new LCObject("GeoObj"); + Random random = new Random(); + LCGeoPoint p1 = new LCGeoPoint(-90 + random.NextDouble() * 180, -180 + random.NextDouble() * 360); + geoObj["location"] = p1; + await geoObj.Save(); + + LCGeoPoint p2 = new LCGeoPoint(p1.Latitude + 0.01, p1.Longitude + 0.01); + + double km = p1.KilometersTo(p2); + TestContext.WriteLine($"km: {km}, {Math.Ceiling(km)}"); + LCQuery query = new LCQuery("GeoObj"); + query.WhereWithinKilometers("location", p2, Math.Ceiling(km)); + Assert.Greater((await query.Find()).Count, 0); + + double miles = p1.MilesTo(p2); + query = new LCQuery("GeoObj"); + query.WhereWithinMiles("location", p2, Math.Ceiling(miles)); + Assert.Greater((await query.Find()).Count, 0); + + double radians = p1.RadiansTo(p2); + query = new LCQuery("GeoObj"); + query.WhereWithinRadians("location", p2, Math.Ceiling(radians)); + Assert.Greater((await query.Find()).Count, 0); + } } } diff --git a/Storage/Storage/Internal/Query/LCCompositionalCondition.cs b/Storage/Storage/Internal/Query/LCCompositionalCondition.cs index cfae0ae..f5c8318 100644 --- a/Storage/Storage/Internal/Query/LCCompositionalCondition.cs +++ b/Storage/Storage/Internal/Query/LCCompositionalCondition.cs @@ -94,6 +94,14 @@ namespace LeanCloud.Storage.Internal.Query { AddOperation(key, "$within", value); } + public void WhereWithinRadians(string key, LCGeoPoint point, double maxDistance) { + Dictionary value = new Dictionary { + { "$nearSphere", point }, + { "$maxDistance", maxDistance } + }; + Add(new LCEqualCondition(key, value)); + } + public void WhereRelatedTo(LCObject parent, string key) { Add(new LCRelatedCondition(parent, key)); } diff --git a/Storage/Storage/Public/LCQuery.cs b/Storage/Storage/Public/LCQuery.cs index 0bb7935..60f6e78 100644 --- a/Storage/Storage/Public/LCQuery.cs +++ b/Storage/Storage/Public/LCQuery.cs @@ -205,6 +205,19 @@ namespace LeanCloud.Storage { return this; } + public LCQuery WhereWithinRadians(string key, LCGeoPoint point, double maxDistance) { + Condition.WhereWithinRadians(key, point, maxDistance); + return this; + } + + public LCQuery WhereWithinMiles(string key, LCGeoPoint point, double maxDistance) { + return WhereWithinRadians(key, point, maxDistance / 3958.8); + } + + public LCQuery WhereWithinKilometers(string key, LCGeoPoint point, double maxDistance) { + return WhereWithinRadians(key, point, maxDistance / 6371.0); + } + /// /// The value corresponding to key is related to the parent. ///