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]; }
}
}
}
중첩 수준 내가 '$'기호를 사용 분리하기 - 몽고의 콜렉션 이름에 금지되어있는 유일한 기호. 이 코드는 수집 schools
FoobarTypesCustom
속성에 찾을 수
MongoDbRefactorer mongoDbRefactorer = new MongoDbRefactorer(Mongo.Database);
mongoDbRefactorer.RenameField("schools", "FoobarTypesCustom$FoobarDefaultName", "FoobarName");
: 사용법은 다음과 같이 할 수 있습니다. 배열과 같은 복잡한 유형이 될 수 있습니다. 그런 다음 FoobarDefaultName
속성을 모두 찾습니다 (FoobarTypesCustom
이 배열이면 반복됩니다). 이름을 FoobarName
으로 바꿉니다. 중첩 수준 및 중첩 배열 수는 중요하지 않습니다.
안녕하세요 이것은 정확하게 찾고 있습니다! 고맙습니다 ! 데이터 유형을 업데이트하는 코드가 있습니까? – user636525
나는 현재 일반적인 해결책이 없다. 그러나 구체적인 예를 들어보십시오. 나는 자바 스크립트 실행을 사용하여 그것을한다. 왜냐하면, 제 생각에는 C#과 mondodb C# 드라이버만을 사용해서는 안됩니다. 당신은 예를 찾을 수 있습니다 [여기] (http://stackoverflow.com/a/11726630/459485). – Dao
이것은 희소 컬렉션이 있지만 생명의 은인 이었기 때문에 if (document == BsonNull.Value) {return; } 제대로 작동하려면 RenameDirect 맨 위에. – dariusriggins