未在合并操作中设置 Azure 搜索 SDK 空字段
Azure Search SDK null field not set on Merge action
我正在使用 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,合并操作会将字段更新为空。事实上,如果我用 JSON 手动发出这个 Http post 请求,这是真的。但 SDK 并未将字段更新为空。我错过了什么?
我找到了 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);
这是 Index
系列方法的类型化重载的已知限制。此处详细描述了该问题:https://github.com/Azure/azure-sdk-for-net/issues/1804
一些解决方法:
- 使用
Index
的无类型版本代替合并方案。
- 使用
Upload
而不是 Merge
。
- 将
[JsonProperty(NullValueHandling = NullValueHandling.Include)]
放在您需要在合并操作中显式设置为 null 的模型 class 的属性上(不推荐 如果您有索引中有很多字段)。
- 实现自定义转换器。
我正在使用 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,合并操作会将字段更新为空。事实上,如果我用 JSON 手动发出这个 Http post 请求,这是真的。但 SDK 并未将字段更新为空。我错过了什么?
我找到了 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);
这是 Index
系列方法的类型化重载的已知限制。此处详细描述了该问题:https://github.com/Azure/azure-sdk-for-net/issues/1804
一些解决方法:
- 使用
Index
的无类型版本代替合并方案。 - 使用
Upload
而不是Merge
。 - 将
[JsonProperty(NullValueHandling = NullValueHandling.Include)]
放在您需要在合并操作中显式设置为 null 的模型 class 的属性上(不推荐 如果您有索引中有很多字段)。 - 实现自定义转换器。