Как найти пользователей в указанных c километрах в asp net core cosmos db sql api - PullRequest
0 голосов
/ 01 апреля 2020

Я использую asp. net core 3.1 с провайдером инфраструктуры ядра. Я хочу найти пользователей в пределах указанных c километров в космосе DB sql API. Но возникли проблемы. Введите код подробно ниже.

Класс сущности ApplicationUser:

using Microsoft.AspNetCore.Identity;

namespace TestApp_Backend_API.Entities
{
    public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string ZipCode { get; set; }

        public GeoLocation DefaultLocationCoordinates { get; set; }
    }
}

Класс геолокации:

using System;
using Newtonsoft.Json;

namespace TestApp_Backend_API.Entities
{
    public class GeoLocation
    {
        public GeoLocation(double lon, double lat)
        {
            Type = "Point";
            if (lat > 90 || lat < -90) { throw new ArgumentException("A latitude coordinate must be a value between -90.0 and +90.0 degrees."); }
            if (lon > 180 || lon < -180) { throw new ArgumentException("A longitude coordinate must be a value between -180.0 and +180.0 degrees."); }
            Coordinates = new double[2] { lon, lat };
        }

        [JsonProperty("type")]
        public string Type { get; set; }
        [JsonProperty("coordinates")]
        public double[] Coordinates { get; set; }

        public double? Lat() => Coordinates?[1];
        public double? Lon() => Coordinates?[0];
    }
}

DbContext:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using TestApp_Backend_API.Entities;
using TestApp_Backend_API.Helpers;

namespace TestApp_Backend_API.DbContexts
{
    public class TestAppContext : IdentityDbContext<ApplicationUser>
    {
        public TestAppContext(DbContextOptions options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.HasDefaultContainer("Users");
            builder.Entity<IdentityUser>().ToContainer("Users");
            builder.Entity<ApplicationUser>().ToContainer("Users");
            builder.Entity<IdentityUserRole<string>>().ToContainer("UserRoles");
            builder.Entity<IdentityUserLogin<string>>().ToContainer("UserLogins");
            builder.Entity<IdentityUserClaim<string>>().ToContainer("UserClaims");
            builder.Entity<IdentityRole>().ToContainer("Roles");
            builder.Entity<IdentityUserToken<string>>().ToContainer("UserTokens");

            builder.Entity<ApplicationUser>(x =>
            {
                x.Property(g => g.DefaultLocationCoordinates)
                    .HasJsonConversion();
            });
        }
    }
}

Расширение HasJsonConversion Метод:

public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder)
        {
            ValueConverter<T, string> converter = new ValueConverter<T, string>(
                v => JsonConvert.SerializeObject(v),
                v => JsonConvert.DeserializeObject<T>(v));

            ValueComparer<T> comparer = new ValueComparer<T>(
                (l, r) => JsonConvert.SerializeObject(l) == JsonConvert.SerializeObject(r),
                v => v == null ? 0 : JsonConvert.SerializeObject(v).GetHashCode(),
                v => JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(v)));

            propertyBuilder.HasConversion(converter);
            propertyBuilder.Metadata.SetValueConverter(converter);
            propertyBuilder.Metadata.SetValueComparer(comparer);

            return propertyBuilder;
        }

Я сохраняю DefaultLocationCoordinates, как это в cosmos db:

"DefaultLocationCoordinates": "{\"type\":\"Point\",\"coordinates\":[31.9,-4.8]}"

Теперь я хочу запрашивать пользователей, как это:

select * from c where
ST_DISTANCE(c.DefaultLocationCoordinates, {'type': 'Point', 'coordinates':[31.9, -4.8]}) < 90000

Но он ничего не возвращает, при сохранении DefaultLocationCoordinates, как это работает нормально:

"DefaultLocationCoordinates": {
        "type": "Point",
        "coordinates": [
            31.9,
            -4.8
        ]
    },

Я сохраняю DefaultLocationCoordinates, как показано ниже, потому что, если эта проблема https://github.com/dotnet/efcore/issues/17317

"DefaultLocationCoordinates": "{\"type\":\"Point\",\"coordinates\":[31.9,-4.8]}"

Может ли кто-нибудь предоставить решение для этого, чтобы я мог выполнить этот запрос:

select * from c where
ST_DISTANCE(c.DefaultLocationCoordinates, {'type': 'Point', 'coordinates':[31.9, -4.8]}) < 90000

Пример данных в космосе db:

{
    "Id": "f38fb31e-49bd-42bb-9a00-d560168bd560",
    "DefaultLocationCoordinates": "{\"type\":\"Point\",\"coordinates\":[-74.505312,40.575405]}",
    "Discriminator": "ApplicationUser",
    "FirstName": "Tom",
    "id": "f38fb31e-49bd-42bb-9a00-d560168bd560",
    "_rid": "4sM9AP3bWYwGAAAAAAAAAA==",
    "_self": "dbs/4sM9AA==/colls/4sM9AP3bWYw=/docs/4sM9AP3bWYwGAAAAAAAAAA==/",
    "_etag": "\"00000000-0000-0000-081a-745b667201d6\"",
    "_attachments": "attachments/",
    "_ts": 1585741276
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...