Elasticsearch NEST частичное обновление анонимного объекта пустым вложенным объектом

Попытка "сбросить" вложенный объект в документе, но он не вернет его пустым.

У меня есть POCO:

public class StreetAddress 
{
    public int HouseNumber { get; set; }
    public string Street { get; set; }
}

public class FullAddress
{
    public string City{ get; set; }

    public string State { get; set; }

    public StreetAddress StreetAddress { get; set; }

    public int Zip { get; set; }

    public List<string> Codes { get; set; }
}

Поэтому в настоящее время, если я создал этот новый документ для FullAddress с уже установленным параметром StreetAddress, документ при запросе выглядит следующим образом:

"_source": {          
    "city": "Los Angeles",          
    "state": "California",          
    "zip": 90019,            
    "streetAddress": {            
        "houseNumber": 1,
        "street": "Apple Street"          
    },
    "codes" : [
        { "la-601" }
    ]     
}

Теперь я хочу вызвать обновление клиента NEST для сброса вложенного объекта StreetAddress:

StreetAddress localStreetAddress = new StreetAddress();

var partialAddress = new 
{ 
    City = "NewCity",
    Zip = 11111,
    StreetAddress = localStreetAddress
};

this._client.Update<ElasticsearchProject, object>(update => update
    .Id(1) 
    .Doc(partialAddress)
);

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

"_source": {          
    "city": "NewCity",          
    "state": "California",          
    "zip": 11111,            
    "streetAddress": {}     
}

Однако частичное обновление делает две вещи, которые нежелательны:

  1. Он только обновляет поля City и Zip и оставляет StreetAddress, как это было раньше, и не очищает его до пустого или нулевого.
  2. Он очищает список кодов для очистки, так как частичное обновление не включает список.

Я знаю, что могу установить для StreetAddress значение null и добавить свойство JSON для включения значения null следующим образом:

[JsonProperty(NullValueHandling = NullValueHandling.Include)]
public StreetAddress StreetAddress { get; set; }

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

"_source": {          
        "city": "NewCity",          
        "state": "California",          
        "zip": 11111,            
        "streetAddress": null     
    }

Не уверен, что есть способ выполнить частичное обновление без перехода по пути к сценарию, чтобы вернуть вложенный объект обратно пустым.

1 ответ

Вложенные объекты фактически отображаются как отдельные скрытые документы в Elasticsearch, и, как вы обнаружили, NEST по умолчанию настроен так, чтобы не отправлять через нулевые значения. конечный результат заключается в том, что на вложенный тип не влияет частичное обновление свойств верхнего уровня.

Один из способов справиться с этим - просто переиндексировать документ снова без StreetAddress. Обновление - это удаление или вставка за кулисы.

В качестве примера

void Main()
{
    var settings = new ConnectionSettings(new Uri("http://localhost:9200"), "address");

    var client = new ElasticClient(settings);

    // create the index
    client.CreateIndex("address", c => c
        .AddMapping<FullAddress>(m => m
            .MapFromAttributes()
        )
    );

    // index our document
    client.Index(new FullAddress
    {
        City = "Los Angeles",
        State = "California",
        Zip = 90019,
        Codes = new List<string>
        {
            "la-601"
        },
        StreetAddress = new StreetAddress
        {
            HouseNumber = 1,
            Street = "Apple Street"
        }
    }, c => c.Id(1));

    // Now at some later point, we need to update it,
    // so get the current document
    var response = client.Get<FullAddress>(1);

    // make the changes to the current document
    var address = response.Source;
    address.StreetAddress = null;

    // and re-index
    client.Index<FullAddress>(address, c => c.Id(1));
}

public class StreetAddress
{
    public int HouseNumber { get; set; }
    public string Street { get; set; }
}

public class FullAddress
{
    public string City { get; set; }

    public string State { get; set; }

    public StreetAddress StreetAddress { get; set; }

    public int Zip { get; set; }

    public List<string> Codes { get; set; }
}

Конечный результат, как и ожидалось

{
  "_index": "address",
  "_type": "fulladdress",
  "_id": "1",
  "_version": 2,
  "found": true,
  "_source": {
    "city": "Los Angeles",
    "state": "California",
    "zip": 90019,
    "codes": [
      "la-601"
    ]
  }
}

При этом вы также можете использовать оптимистический контроль параллелизма для обработки любых изменений между get а также index,

Другие вопросы по тегам