Индексатору поиска 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, которые объясняют, какие типы экземпляров географии принимаются:
- https://msdn.microsoft.com/en-us/library/azure/dn798938.aspx
- https://msdn.microsoft.com/en-us/library/azure/dn946880.aspx?f=255&MSPPError=-2147217396
В основном это должно быть в формате 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))]