2016-12-13 9 views
2

に設定されていない私は、私は次のことをしようとしている、Azureの検索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にします。それは無視されます。 null以外の値を設定した場合は、設定されます。

ドキュメントhereによると、マージ操作では、フィールドがnullに更新されます。実際、JSONを使ってこのHttp投稿要求を手動で作成すると、これは真です。しかし、SDKはフィールドをnullに更新していません。私は何が欠けていますか?

答えて

1

これは、メソッドのIndex家族のタイプされたオーバーロードの既知の制限です。問題は、ここで詳細に説明されていますhttps://github.com/Azure/azure-sdk-for-net/issues/1804

いくつかの回避策:

  1. がマージシナリオのための代わりIndexの型指定されていないバージョンを使用してください。
  2. Mergeの代わりにUploadを使用してください。
  3. マージ操作で明示的にnullに設定する必要があるモデルクラスのプロパティに[JsonProperty(NullValueHandling = NullValueHandling.Include)]を入力します(はインデックスにフィールドが多い場合はを推奨しません)。
  4. カスタムコンバータを実装します。
+0

ありがとう、ブルース!私は型なしのバージョン(Documentを使用)を知らなかった。私はカスタムコンバータの代わりにそれを使用します。私はJsonPropertyAttributeについても忘れていました。すべてのフィールドでJsonPropertyを使用することをお勧めしない理由を教えてください。 –

+0

主にパフォーマンス。スキーマが非常に広い場合(フィールド数は100)、索引バッチ要求内のすべてのドキュメントに100を送信すると、ネットワーク帯域幅が非常に浪費されます。 –

1

the culprit in the Azure Search SDK sourceが見つかりました。

行51、settings.NullValueHandling = NullValueHandling.Ignore;が設定しようとしていた設定を上書きしています。私はおそらくこれについてGithubで問題を作り上げています。

現時点では、回避策としてカスタムコンバータを使用しています。ブルースによって記載されている

他の二つの優れたオプション:型なしでドキュメントを使用して、正しいシリアル化を取得するために、フィールド上のJsonPropertyAttributeを使用して

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

// ... 

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

// ... 

編集と同様に

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 Document 
{ 
    ["Id"] = "94303", 
    ["ApprovedOn"] = null, 
    ["IgnoredOn"] = null 
}; 

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