RavenDB 迁移:将 属性 从字符串更新为字符串数组

RavenDB Migration: update property from string to array of strings

我有一个名为 Actions 的文档集合。数据库中的操作如下所示:

{
    "Name": "Name1",
    "ActionType": "typeA"
}

我需要迁移所有 Action,这样 ActionType 属性 就会包含一个字符串数组:

{
    "Name": "Name1",
    "ActionType": ["typeA"]
}

我不想像提到的那样在我的项目中创建任何转换器 here。 那应该是一个简单的实用程序,可以单独运行。

想法是加载所有文档,进行必要的更改并保存它们(如 here)。我当前的代码看起来像这样,但它不能正常工作:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Raven.Client;
using Raven.Client.Document;
using Raven.Client.Linq;
using Raven.Json.Linq;

namespace RavenDbMigration
{
    public class SimpleMigrator
    {
        private readonly IDocumentStore _documentStore;

        public SimpleMigrator(IDocumentStore documentStore)
        {
            _documentStore = documentStore;
        }

        public void Run()
        {
            using (IDocumentSession session = _documentStore.OpenSession())
            {
                var fullRavenIdsList = new List<string> {"1", "2", "3"};

                RavenJObject[] ravenJObjects = session.Load<RavenJObject>(fullRavenIdsList); // Problem here - ravenJObjects contains 3 null values instead of actions
                foreach (var ravenJObject in ravenJObjects)
                {
                    var results = ravenJObject["Actions"] as RavenJArray;
                    if (results != null)
                    {
                        foreach (var result in results)
                        {
                            if (result != null && result.ContainsKey("ActionType"))
                            {
                                var actionTypes = new List<string>();

                                var actionType = result.Value<string>("ActionType");
                                if (actionType != null)
                                {
                                    actionTypes.Add(actionType);
                                }
                                result["ActionType"] = new RavenJArray(actionTypes);
                            }
                        }
                    }
                }

                session.SaveChanges();
            }
        }    
    }
}

我使用 RavenDB.Client 版本 2.5.2700。

您需要创建一个类型为 List 的新字段,然后将数据迁移到列表中,而且您没有分页,因此您需要分页以获取所有数据才能为所有记录工作。

之后,您从模型中删除旧的单个字符串 属性,然后当您的数据进行更多更新等时,这个 属性 将被删除。

你按照他们告诉你的方式去做,在 link 提供的情况下,创建那个 post 的人拥有 RavenDB 并且知道他在说什么,如果他说这是最好的方法,你通常可以保证它是。

您可以通过 Raven Studio 或代码修补文档集 "Actions"。

this.ActionType = [this.ActionType];

这将导致文档如下所示:

"Name": "Name1",
"ActionType": [
  "typeA"
]

希望这对您有所帮助!

如果有人对如何从代码执行此迁移感兴趣,请查看示例代码:

using System.Collections.Generic;
using System.Linq;
using Raven.Client;
using Raven.Client.Linq;
using Raven.Imports.Newtonsoft.Json.Linq;
using Raven.Json.Linq;

namespace RavenDbMigration
{
    public class SimpleMigrator
    {
        private readonly IDocumentStore _documentStore;
        private readonly int _pageSize;

        public SimpleMigrator(IDocumentStore documentStore, int pageSize = 128)
        {
            _pageSize = pageSize;
            _documentStore = documentStore.Initialize();
        }

        public void Run(string databasName)
        {
            var pageIndex = 0;
            while (true)
            {
                using (var session = _documentStore.OpenSession(databasName))
                {
                    var ravenJObjects = session.Query<RavenJObject>().Skip(_pageSize * pageIndex).Take(_pageSize);

                    if (!ravenJObjects.Any()) break;

                    foreach (var ravenJObject in ravenJObjects)
                    {
                        var ravenJTokenActionType = ravenJObject.SelectToken("ActionType");

                        if (ravenJTokenActionType == null || ravenJTokenActionType.Type != JTokenType.String) continue;

                        var actionType = ravenJTokenActionType.ToString();

                        var actionTypes = new List<string> { actionType };

                        ravenJObject["ActionType"] = new RavenJArray(actionTypes);

                        //// In case you want to rename property
                        //ravenJObject["ActionTypes"] = new RavenJArray(actionTypes);
                        //ravenJObject.Remove("ActionType");
                    }

                    session.SaveChanges();
                }

                pageIndex++;
            }
        }
    }
}