Динамические шаблоны хорошо подходят для вашего варианта использования, эта функция дает вам отличный способ контролировать, как elasticsearch отображает вашу динамическую схему данных.
Вы можете использовать сопоставление. параметр и тип поля управления на основе имени поля. Если экземпляр DatasetField
имеет IsGeoPoint
, установленный в true
, мы можем добавить к имени поля elasticsearch префикс GeoPoint и настроить динамический шаблон для создания поля goe_point
для имен с префиксом GeoPoint.
{
"mappings": {
"dynamic_templates": [{
"geo_shape": {
"match": "GeoShape*",
"mapping": {
"type": "geo_shape"
}
}
}, {
"geo_point": {
"match": "GeoPoint*",
"mapping": {
"type": "geo_point"
}
}
}
]
}
}
Вот пример приложения C#, показывающего его в действии.
class Program
{
static async Task Main(string[] args)
{
string indexName = "my_index";
var connectionSettings = new ConnectionSettings(new Uri("http://localhost:9200"));
connectionSettings.DefaultIndex(indexName);
var elasticClient = new ElasticClient(connectionSettings);
await elasticClient.Indices.DeleteAsync(indexName);
//create index mapping with two dynamic templates,
//based on field suffix elasticsearch will map field to specific type
var indexResponse = await elasticClient.Indices.CreateAsync(indexName, d => d
.Map(map => map
.DynamicTemplates(dt => dt
.DynamicTemplate("geo_shape", gs => gs.Match("GeoShape*").Mapping(m => m.GeoShape(s => s)))
.DynamicTemplate("geo_point", gs => gs.Match("GeoPoint*").Mapping(m => m.GeoPoint(p => p)))
)));
//some same data matching your schema
var data = new List<DatasetField>
{
new () { Name = "Field1", IsGeoPoint = true },
new () { Name = "Field2", IsGeoShape = true },
};
var document = new EsDocument();
foreach (var datasetField in data)
{
//if the field is of type geo shape, prefix field name with GeoShape,
//geo_shape dynamic template will match field name and will create geo_point type for it
if (datasetField.IsGeoShape)
{
document.Add($"GeoShape{datasetField.Name}", new PointGeoShape(new GeoCoordinate(0, 0)));
}
//if the field is of type geo point, prefix field name with GeoPoint,
//geo_point dynamic template will match field name and will create geo_shape type for it
if (datasetField.IsGeoPoint)
{
document.Add($"GeoPoint{datasetField.Name}", new GeoLocation(0, 0));
}
}
var response = await elasticClient.IndexDocumentAsync(document);
}
//this class is just an alias to dictionary
class EsDocument : Dictionary<string,object>{}
class DatasetField
{
public string Name { get; set; }
public bool IsGeoShape { get; set; }
public bool IsGeoPoint { get; set; }
}
}
Это создаст следующее отображение elasticsearch
{
"my_index": {
"mappings": {
"dynamic_templates": [{
"geo_shape": {
"match": "GeoShape*",
"mapping": {
"type": "geo_shape"
}
}
}, {
"geo_point": {
"match": "GeoPoint*",
"mapping": {
"type": "geo_point"
}
}
}
],
"properties": {
"GeoPointField1": {
"type": "geo_point"
},
"GeoShapeField2": {
"type": "geo_shape"
}
}
}
}
}
Когда дело доходит до массовой индексации документов, проще всего использовать метод расширения IndexManyAsync
.
await elasticClient.IndexManyAsync(new List<EsDocument>());
Также ознакомьтесь с этим сообщением в блоге подробное описание индексации нескольких документов. Проверьте раздел «Несколько документов».
ОБНОВЛЕНИЕ: добавьте новый динамический шаблон в сопоставление с существующими динамическими шаблонами.
var map = (await elasticClient.Indices.GetMappingAsync<EsDocument>()).Indices["your_index_name"];
var dynamicTemplates = map.Mappings.DynamicTemplates;
//add new
dynamicTemplates.Add(new KeyValuePair<string, IDynamicTemplate>());
await elasticClient.Indices.PutMappingAsync(new PutMappingRequest("your_index_name") { DynamicTemplates = dynamicTemplates });
person
Rob
schedule
10.06.2021