Индексатору поиска Azure не удается получить GeographyPoint, поданный из документа в DocumentDB

У меня возникла проблема при попытке проиндексировать документ, хранящийся в коллекции DocumentDb.

Источник данных индексатора был определен с помощью пользовательского SQL для извлечения измененных документов. Документ, который я хочу проиндексировать, имеет свойство с именем LocationGP который является Microsoft.Spatial.GeographyPoint и сопоставлен с полем индекса с тем же именем и определен как DataType.GeographyPoint

Ошибка, которую я получаю при попытке создать индексатор:

Столбец LocationGP имеет тип JObject, который не совместим с полем типа Edm.GeographyPoint в индексе.

Есть идеи?

Это определение источника данных:

  return new DataSource()
                {
                    Name = "opportunities-datasource",
                    Container = new DataContainer()
                    {
                        Name = "Companies",
                        Query = @"SELECT    o.id,
                                            o.CompanyName,
                                            o.LocationGP,
                                            o.Location.CityName AS LocationCity,
                                            o.Location.StateName AS LocationState,
                                            o.Location.CountryName AS LocationCountry,
                                            o._ts
                                FROM Companies o WHERE o.DocType = 1 AND o._ts > @HighWaterMark"
                    },
                    Type = "documentdb",
                    Credentials = new DataSourceCredentials()
                    {
                        ConnectionString = String.Format("AccountEndpoint={0};AccountKey={1};Database=CompaniesDb", DocumentDbEndpointUri, DocumentDbPrimaryKey)
                    },
                    DataChangeDetectionPolicy = new HighWaterMarkChangeDetectionPolicy("_ts"),
                    DataDeletionDetectionPolicy = new SoftDeleteColumnDeletionDetectionPolicy("Status", "2")
                };

Это документ:

[{
    "id": "088e1e97-6d59-40ad-a9be-620fdc7938c7",
    "CompanyName": "Neptune",
    "LocationGP": {
      "Latitude": 39.8010482788086,
      "Longitude": -89.6436004638672,
      "IsEmpty": false,
      "Z": null,
      "M": null,
      "CoordinateSystem": {
        "EpsgId": 4326,
        "Id": "4326",
        "Name": "WGS84"
      }
    },
    "Location": {
      "CityName": "Springfield",
      "CountryName": "US",
      "StateName": "IL"
    },
    "Status": 1,
    "DocType": 1,
    "Timestamp": "2016-08-19T16:08:46.0481948Z",
    "_ts": 1471622922
  }]

4 ответа

Решение

Вот еще два документа по поиску Azure, которые объясняют, какие типы экземпляров географии принимаются:

В основном это должно быть в формате GeoJSON "Point".

Проблема заключалась в том, что Edm.GeographyPoint имеет другой формат, чем Microsoft.Spatial.GeographyPoint,

Чтобы это работало, я просто создал класс EdmGeograpyPoint как это:

public class EdmGeographyPoint
{
    public EdmGeographyPoint(double longitude, double latitude)
    {
        coordinates = new double[] { longitude, latitude };
        type = "Point";
    }

    public string type { get; private set; }
    public double[] coordinates { get; private set; }
}

Затем я заменил тип свойства LocationGP на EdmLocation.

Возможно, есть лучшее решение, но документация сбивает с толку эту тему: https://azure.microsoft.com/en-us/documentation/articles/search-howto-dotnet-sdk/

Мне не удалось успешно использовать ни одно из вышеперечисленных решений для извлечения данных GeographyLocation из нашего экземпляра поиска Azure. Мне удалось заставить его работать с небольшой корректировкой пользовательского класса географического местоположения. Я просто использовал конвертер JSONtoC# для создания класса. Это работает со значениями, содержащими координаты и нулевые местоположения.

         public class ASLocation
    {
        [SimpleField(IsFilterable = true)]
        public string type { get; set; }

        [SimpleField(IsFilterable = true, IsSortable = true)]
        public List<double> coordinates { get; set; }
    }

Я немного опоздал с этим ответом, но надеюсь, что кому-то это поможет.

На мой взгляд, самый простой способ справиться с этим - продолжать использовать "встроенные" классы / фреймворк без необходимости создавать свой собственный сложный тип.

Я решил эту проблему с помощью JsonConverter, который использовал пространство имен Microsoft.Azure.Search.Serialization. Это пространство имен имеет расширения GeographyPoint, то есть расширения ReadGeoJsonPoint() и WriteJson().

Я сделал следующее:

 //    1. Create a JsonConverter
   using Microsoft.Azure.Search.Serialization;
   public class GeographyPointJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(GeographyPoint);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return reader.ReadGeoJsonPoint();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteGeoJsonPoint(value as GeographyPoint);
        }
    }

    //2. Added the convert to the property I was looking to index
    [JsonConverter(typeof(GeographyPointJsonConverter))]
Другие вопросы по тегам