【问题标题】:RavenDB: PatchRequest to update/merge property that may not exist in documentRavenDB:PatchRequest 更新/合并文档中可能不存在的属性
【发布时间】:2018-07-26 11:59:25
【问题描述】:

我有一个具有以下域模型的文档:

class Entity
{
    ...
    Dictionary<string, string> Settings { get; set; }
    ...
}

并且需要更新指定的集合。但不会覆盖 - 合并与传入的更新。由于我需要以这种方式处理数千个文档,因此我选择了 PatchCommand 以获得更好的性能。得到以下结果:

new PatchCommandData
{
    Key = upd.EntityId,
    Patches = new[]
    {
        // Foreach incoming Setting remove existing value (if any) and add the new one
        new PatchRequest
        {
            Type = PatchCommandType.Modify,
            Name = nameof(Entity.Settings),
            Nested = upd.UpdatedSettings.Keys
                .Select(x => new PatchRequest
                {
                    Type = PatchCommandType.Unset,
                    Name = x
                })
                .ToArray()
                .Union(upd.UpdatedSettings.Keys
                .Select(x => new PatchRequest
                {
                    Type = PatchCommandType.Set,
                    Name = x,
                    Value = upd.UpdatedSettings[x]
                })
                .ToList())
                .ToArray(),
            Value = RavenJToken.FromObject(upd.UpdatedSettings)
        }
    }
}

这样执行下一次更新:

Before: { Setting1 = "Value1", Setting2 = "Value2" }
Update request: { Setting2 = "NewValue2", Setting3 = "Value3" }
After: { Setting1 = "Value1", Setting2 = "NewValue2", Setting3 = "Value3" }

但是.. 总有一个“但是”。如果 db 中存在 没有设置属性的文档,则提供 patch 将引发错误,提示“无法从设置中修改值,因为未找到”。

我找不到将补丁模式切换为“设置”与“即时修改”的任何选项。并且没有加载所有文档的选项,在应用程序端应用更新并更新数千个文档。 我能看到的唯一合理的选择是在类构造函数中为 Settings 属性创建 Dictionary 实例。

伙计们,你能建议一些其他的选择吗?

附言RavenDB 版本仅限于 3.5

【问题讨论】:

    标签: c# .net database nosql ravendb


    【解决方案1】:

    完成。您可以在下面找到最终版本。实际上,使用了 ScriptedPatchCommandData。它包含 JavaScript 主体,Raven 将对文档进行评估和执行。从性能的角度来看,它可能不是最佳选择。但事实证明,没有什么重要的。希望它可能对某人有所帮助。

    const string fieldParameterName = "fieldName";
    const string valueParameterName = "value";
    
    var patch = updates
        .Select(update => new ScriptedPatchCommandData
        {
            Key = update.EntityId,
            Patch = new ScriptedPatchRequest
            {
                Script = $"this[{fieldParameterName}] = _.assign({{}}, this[{fieldParameterName}], JSON.parse({valueParameterName}));",
                Values = new Dictionary<string, object>
                {
                    { 
                         fieldParameterName,
                         nameof(Entity.Settings)
                    },
                    {
                        valueParameterName,
                        JsonConvert.SerializeObject(update.UpdatedSettings)
                    }
                }
            }
        })
        .ToList();
    
    return await DocumentStore.AsyncDatabaseCommands.BatchAsync(patch);
    

    【讨论】:

      猜你喜欢
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2021-01-07
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      相关资源
      最近更新 更多