sql >> データベース >  >> NoSQL >> MongoDB

配列にある複合型のフィールドの名前を変更します

    MongoDBの任意のフィールドの名前を変更するための特別なタイプを実装しました。これがそれです:

    using System.Linq;
    using MongoDB.Bson;
    using MongoDB.Driver;
    
    namespace DatabaseManagementTools
    {
        public class MongoDbRefactorer
        {
            protected MongoDatabase MongoDatabase { get; set; }
    
            public MongoDbRefactorer(MongoDatabase mongoDatabase)
            {
                MongoDatabase = mongoDatabase;
            }
    
            /// <summary>
            /// Renames field
            /// </summary>
            /// <param name="collectionName"></param>
            /// <param name="oldFieldNamePath">Supports nested types, even in array. Separate nest level with '$': "FooField1$FooFieldNested$FooFieldNestedNested"</param>
            /// <param name="newFieldName">Specify only field name without path to it: "NewFieldName", but not "FooField1$NewFieldName"</param>
            public void RenameField(string collectionName, string oldFieldNamePath, string newFieldName)
            {
                MongoCollection<BsonDocument> mongoCollection = MongoDatabase.GetCollection(collectionName);
                MongoCursor<BsonDocument> collectionCursor = mongoCollection.FindAll();
    
                PathSegments pathSegments = new PathSegments(oldFieldNamePath);
    
                // Rename field in each document of collection
                foreach (BsonDocument document in collectionCursor)
                {
                    int currentSegmentIndex = 0;
                    RenameField(document, pathSegments, currentSegmentIndex, newFieldName);
    
                    // Now document is modified in memory - replace old document with new in mongo:
                    mongoCollection.Save(document);
                }
            }
    
            private void RenameField(BsonValue bsonValue, PathSegments pathSegments, int currentSegmentIndex, string newFieldName)
            {
                string currentSegmentName = pathSegments[currentSegmentIndex];
    
                if (bsonValue.IsBsonArray)
                {
                    var array = bsonValue.AsBsonArray;
                    foreach (var arrayElement in array)
                    {
                        RenameField(arrayElement.AsBsonDocument, pathSegments, currentSegmentIndex, newFieldName);
                    }
                    return;
                }
    
                bool isLastNameSegment = pathSegments.Count() == currentSegmentIndex + 1;
                if (isLastNameSegment)
                {
                    RenameDirect(bsonValue, currentSegmentName, newFieldName);
                    return;
                }
    
                var innerDocument = bsonValue.AsBsonDocument[currentSegmentName];
                RenameField(innerDocument, pathSegments, currentSegmentIndex + 1, newFieldName);
            }
    
            private void RenameDirect(BsonValue document, string from, string to)
            {
                BsonElement bsonValue;
                bool elementFound = document.AsBsonDocument.TryGetElement(from, out bsonValue);
                if (elementFound)
                {
                    document.AsBsonDocument.Add(to, bsonValue.Value);
                    document.AsBsonDocument.Remove(from);
                }
                else
                {
                    // todo: log missing elements
                }
            }
        }
    }
    

    パスセグメントを保持するためのヘルパータイプ:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace DatabaseManagementTools
    {
        public class PathSegments : IEnumerable<string>
        {
            private List<string> Segments { get; set; }
    
            /// <summary>
            /// Split segment levels with '$'. For example: "School$CustomCodes"
            /// </summary>
            /// <param name="pathToParse"></param>
            public PathSegments(string pathToParse)
            {
                Segments = ParseSegments(pathToParse);
            }
    
            private static List<string> ParseSegments(string oldFieldNamePath)
            {
                string[] pathSegments = oldFieldNamePath.Trim(new []{'$', ' '})
                    .Split(new [] {'$'}, StringSplitOptions.RemoveEmptyEntries);
    
                return pathSegments.ToList();
            }
    
            public IEnumerator<string> GetEnumerator()
            {
                return Segments.GetEnumerator();
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
    
            public string this[int index]
            {
                get { return Segments[index]; }
            }
        }
    }
    

    ネストレベルを区切るために、「$」記号を使用します。これは、mongoのコレクション名で禁止されている唯一の記号です。使用法は次のようになります。

    MongoDbRefactorer mongoDbRefactorer = new MongoDbRefactorer(Mongo.Database);
    mongoDbRefactorer.RenameField("schools", "FoobarTypesCustom$FoobarDefaultName", "FoobarName");
    

    このコードはコレクションschoolsにあります FoobarTypesCustom 財産。複合型なので配列にすることができます。次に、すべてのFoobarDefaultNameを検索します プロパティ(FoobarTypesCustomの場合 は配列であり、それを反復処理します)、名前をFoobarNameに変更します。 。ネストレベルとネストされた配列の数は関係ありません。




    1. mongodbの配列に対してANDクエリをどのように実行しますか?

    2. マングースで個別の値を照会するにはどうすればよいですか?

    3. 複数のコレクションでトランザクションを実行中にMongoDBAtlasエラーが発生しました(コード8000)

    4. 私が5人のように説明する:テキストと画像フィールドのあるフォーム>ルート>コントローラー> MongoDBドキュメントへの書き込み-GridFSはどこに行きますか?