PUT Mapping с использованием высокоуровневого Nest Client и AutoMap - PullRequest
0 голосов
/ 04 апреля 2019

Я создаю индексы Elasticsearch, используя следующий фрагмент кода:

ICreateIndexResponse createIndexResponse = elasticClient.CreateIndex(IndexName, c => c
    .Mappings(ms => ms
        .Map<Document>(m => m.AutoMap())
    )
);

Класс Document представляет собой POCO с сопоставлениями атрибутов.

Я хотел бы добавить поля вмое отображение.Это представляется возможным при использовании API сопоставления пут:

PUT my_index 
{
  "mappings": {
    "_doc": {
      "properties": {
        "name": {
          "properties": {
            "first": {
              "type": "text"
            }
          }
        },
        "user_id": {
          "type": "keyword"
        }
      }
    }
  }
}

PUT my_index/_mapping/_doc
{
  "properties": {
    "name": {
      "properties": {
        "last": { 
          "type": "text"
        }
      }
    },
    "user_id": {
      "type": "keyword",
      "ignore_above": 100 
    }
  }
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html

Обратите внимание, что первый PUT создает индекс и отображение.Второй PUT добавляет и модифицирует поля.Я хочу иметь возможность выполнить второй PUT.

Идеальным сценарием будет добавление свойств в мой класс Document, вызов AutoMap и использование клиента для вызова API отображения PUT.Новые свойства будут добавлены в мое отображение, а ранее существовавшие свойства были обновлены / проигнорированы в зависимости от ситуации.

Возможно ли это?Должен ли я снова вызывать метод CreateIndex с определенными параметрами?

1 Ответ

1 голос
/ 04 апреля 2019

API-интерфейс Put Mapping предоставляется клиенту как .Map<T>

var client = new ElasticClient();

var putMappingResponse = client.Map<Document>(m => m
    .AutoMap()
);

Это позволит автоматизировать все свойства Document. Я считаю, что Elasticsearch просто не сможет использовать те сопоставления, которые уже существуют, и добавит новые сопоставления.

Если вы хотите отправить только те свойства, которые еще не сопоставлены, это было бы возможно, если получить автоматически сопоставленные свойства Document, извлекать сопоставления из индекса, исключая последнее из первого , а затем отправив их с .Map<T>(). Что-то вроде

var defaultIndex = "properties_example";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

var settings = new ConnectionSettings(pool)
    .DefaultIndex(defaultIndex);

var client = new ElasticClient(settings);

if (!client.IndexExists(defaultIndex).Exists)
{
    var createIndexResponse = client.CreateIndex(defaultIndex, c => c
        .Mappings(m => m
            .Map<Document>(mm => mm.AutoMap())
        )
    );
}

var properties = new PropertyWalker(typeof(Document), null).GetProperties();

// will use the index inferred for Document, or the default index if none
// specified. Can specify an index on this call if you want to  
var getMappingResponse = client.GetMapping<Document>();

var indexedMappings = getMappingResponse
    // Use the index name to which the call was made.
    .Indices[defaultIndex]
    .Mappings[typeof(Document)]
    .Properties;

var propertiesToIndex = new Dictionary<PropertyName, IProperty>();  
foreach(var property in properties)
{
    if (!indexedMappings.ContainsKey(property.Key))
    {
        propertiesToIndex.Add(property.Key, property.Value);
    }
}

// map new properties only if there are some to map
if (propertiesToIndex.Any())
{
    var request = new PutMappingRequest<Document>()
    {
        Properties = new Properties(propertiesToIndex)
    };

    var putMappingResponse = client.Map(request);
}
...