【问题标题】:Azure Search SDK null field not set on Merge action合并操作上未设置 Azure 搜索 SDK 空字段
【发布时间】:2016-12-14 07:38:04
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

    一些解决方法:

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

    【讨论】:

    • 谢谢布鲁斯!我不知道无类型版本(使用 Document)。我将使用它而不是自定义转换器。我也忘记了 JsonPropertyAttribute。你能说说为什么不建议在每个字段上都有 JsonProperty 吗?
    • 性能为主。如果您有一个非常广泛的架构(想想 100 个字段),为索引批处理请求中的每个文档发送 100 个空值是非常浪费网络带宽的。
    【解决方案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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-02
      相关资源
      最近更新 更多