未在合并操作上设置Azure Search SDK空字段

时间:2016-12-13 01:27:54

标签: azure azure-search azure-search-.net-sdk

我正在使用Microsoft.Azure.Search版本3.0.1,

我正在尝试以下方法:

// subset of my index's fields
private class SyncFields
{   
    public string Id { get; set; }
    public DateTimeOffset? ApprovedOn { get; set; }
    public DateTimeOffset? IgnoredOn { get; set; }
}

public void Sync()
{
    var sync = new SyncFields
    {
        Id = "94303",
        ApprovedOn = null,
        IgnoredOn = DateTime.UtcNow
    };

    var searchClient = new SearchServiceClient("xxxx",
        new SearchCredentials("xxxx"));
    searchClient.SerializationSettings.NullValueHandling = NullValueHandling.Include;

    using (var client = searchClient.Indexes.GetClient("xxxx"))
    {
        client.SerializationSettings.NullValueHandling = NullValueHandling.Include;
        var batch = IndexBatch.Merge<SyncFields>(new[] { sync });
        client.Documents.Index<SyncFields>(batch);
    }
}

这不是将ApprovedOn设置为null。它忽略了它。如果我设置了一个非空值,它会设置它。

根据文档here,合并操作将字段更新为null。事实上,如果我用JSON手动发出这个Http post请求,这是真的。但SDK没有将字段更新为null。我错过了什么?

2 个答案:

答案 0 :(得分:2)

我找到了the culprit in the Azure Search SDK source

第51行,settings.NullValueHandling = NullValueHandling.Ignore;覆盖了我尝试设置的设置。我可能会在Github上提出这个问题。

目前,我正在使用自定义转换器作为解决方法。

public class DefaultDateTimeOffsetIsNullConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(DateTimeOffset?));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var date = (DateTimeOffset?)value;
        if (date == default(DateTimeOffset))
        {
            writer.WriteNull();
        }
        else
        {
            writer.WriteValue(date);
        }
    }

    public override bool CanRead => false;

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

var sync = new SyncFields
{
    Id = "94303",
    ApprovedOn = default(DateTimeOffset), // set to null
    IgnoredOn = DateTime.UtcNow
};

// ...

client.SerializationSettings.Converters.Add(new DefaultDateTimeOffsetIsNullConverter());

// ...

修改

Bruce列出的另外两个优先选项:使用无类型的Document,并使用字段上的JsonPropertyAttribute来获得正确的序列化。使用Document非常适合我的用例,没有序列化问题或自定义转换器:

var sync = new Document
{
    ["Id"] = "94303",
    ["ApprovedOn"] = null,
    ["IgnoredOn"] = null
};

// ... the same as before:
var batch = IndexBatch.Merge(new[] { sync });
await client.Documents.IndexAsync(batch);

答案 1 :(得分:2)

这是Index系列方法的类型重载的已知限制。此处详细介绍了此问题:https://github.com/Azure/azure-sdk-for-net/issues/1804

一些解决方法:

  1. 使用无类型版本的Index代替合并方案。
  2. 使用Upload代替Merge
  3. [JsonProperty(NullValueHandling = NullValueHandling.Include)]放在模型类的属性上,您需要在合并操作中显式设置为null(如果索引中有许多字段,不推荐)。
  4. 实施自定义转换器。