Ответ 1
Я решил написать свои примеры на С#, поскольку я больше знаком с драйвером С#, и это тег, указанный в вопросе. Вы можете запустить агрегацию против каждой коллекции, чтобы найти все поля верхнего уровня и их типы (mongodb) для каждого документа.
Агрегация выполняется в 3 этапа. Предположим, что входные данные - это 10 документов, все из которых имеют следующую форму:
{
"_id": ObjectId("myId"),
"num": 1,
"str": "Hello, world!"
}
-
$project
Преобразование каждого документа в массив документов со значениямиfieldName
иfieldType
. Выводит 10 документов с одним полем массива. Поле массива будет иметь 3 элемента. -
$unwind
массивы полевой информации. Выводит 30 документов каждый с одним полем, соответствующим элементу, из выхода шага 1. -
$group
поля поfieldName
иfieldType
для получения отдельных значений. Выводит 3 документа. Поскольку в этом примере все поля с одинаковым именем имеют одинаковый тип, для каждого поля есть только один конечный выходной документ. Если два разных документа определили одно и то же поле, одно в виде строки и одно как int, в этом результирующем наборе для обоих будут отдельные записи.
// Define our aggregation steps.
// Step 1, $project:
var project = new BsonDocument
{ {
"$project", new BsonDocument
{
{
"_id", 0
},
{
"fields", new BsonDocument
{ {
"$map", new BsonDocument
{
{ "input", new BsonDocument { { "$objectToArray", "$$ROOT" } } },
{ "in", new BsonDocument {
{ "fieldName", "$$this.k" },
{ "fieldType", new BsonDocument { { "$type", "$$this.v" } } }
} }
}
} }
}
}
} };
// Step 2, $unwind
var unwind = new BsonDocument
{ {
"$unwind", "$fields"
} };
// Step 3, $group
var group = new BsonDocument
{
{
"$group", new BsonDocument
{
{
"_id", new BsonDocument
{
{ "fieldName", "$fields.fieldName" },
{ "fieldType", "$fields.fieldType" }
}
}
}
}
};
// Connect to our database
var client = new MongoClient("myConnectionString");
var db = client.GetDatabase("myDatabase");
var collections = db.ListCollections().ToEnumerable();
/*
We will store the results in a dictionary of collections.
Since the same field can have multiple types associated with it the inner value corresponding to each field is 'List<string>'.
The outer dictionary keys are collection names. The inner dictionary keys are field names.
The inner dictionary values are the types for the provided inner dictionary key (field name).
List<string> fieldTypes = allCollectionFieldTypes[collectionName][fieldName]
*/
Dictionary<string, Dictionary<string, List<string>>> allCollectionFieldTypes = new Dictionary<string, Dictionary<string, List<string>>>();
foreach (var collInfo in collections)
{
var collName = collInfo["name"].AsString;
var coll = db.GetCollection<BsonDocument>(collName);
Console.WriteLine("Finding field information for " + collName);
var pipeline = PipelineDefinition<BsonDocument, BsonDocument>.Create(project, unwind, group);
var cursor = coll.Aggregate(pipeline);
var lst = cursor.ToList();
allCollectionFieldTypes.Add(collName, new Dictionary<string, List<string>>());
foreach (var item in lst)
{
var innerDict = allCollectionFieldTypes[collName];
var fieldName = item["_id"]["fieldName"].AsString;
var fieldType = item["_id"]["fieldType"].AsString;
if (!innerDict.ContainsKey(fieldName))
{
innerDict.Add(fieldName, new List<string>());
}
innerDict[fieldName].Add(fieldType);
}
}
Теперь вы можете выполнять итерацию по вашему набору результатов:
foreach(var collKvp in allCollectionFieldTypes)
{
foreach(var fieldKvp in collKvp.Value)
{
foreach(var fieldType in fieldKvp.Value)
{
Console.WriteLine($"Collection {collKvp.Key} has field name {fieldKvp.Key} with type {fieldType}");
}
}
}