4

我正在使用 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为空。它忽略它。如果我设置一个非空值,它会设置它。

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

4

2 回答 2

4

这是Index方法族的类型化重载的一个已知限制。此处详细描述了该问题:https ://github.com/Azure/azure-sdk-for-net/issues/1804

一些解决方法:

  1. 将无类型版本的Index改为用于合并方案。
  2. 使用Upload而不是Merge.
  3. 放置[JsonProperty(NullValueHandling = NullValueHandling.Include)]您需要在合并操作中显式设置为 null 的模型类的属性(如果您的索引中有很多字段,则不推荐)。
  4. 实现自定义转换器。
于 2016-12-13T19:56:28.900 回答
2

在 Azure 搜索 SDK 源代码中找到了罪魁祸首

第 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);
于 2016-12-13T04:42:04.493 回答