使用FSharp获取有关MongoDB集合的一般信息

Ste*_*ven 12 c# f# mongodb

我可以检索有关的所有集合的基本信息MongoDBF#

我有一个MongoDB> 450集合.我可以访问数据库

open MongoDB.Bson
open MongoDB.Driver
open MongoDB.Driver.Core 
open MongoDB.FSharp
open System.Collections.Generic

let connectionString = "mystring"
let client = new MongoClient(connectionString)
let db = client.GetDatabase(name = "Production")
Run Code Online (Sandbox Code Playgroud)

我曾考虑尝试让所有集合循环遍历每个集合名称,并获得有关每个集合的基本信息

let collections = db.ListCollections()
Run Code Online (Sandbox Code Playgroud)

db.GetCollection([name of a collection])
Run Code Online (Sandbox Code Playgroud)

但是db.GetCollection([name])要求我定义一个类型来提取每个集合的信息.这对我来说很有挑战性,因为我不想为每个集合定义一个类型,其中有> 450,坦率地说,我对这个数据库并不是很了解.(实际上,我的组织中没有人这样做;这就是为什么我要整理一个非常基本的数据字典.)

是否真的需要为每个集合定义类型?我是否可以使用此处提供MongoCollection方法而无需为每个集合定义类型?


编辑:最后,我希望能够输出集合名称,每个集合中的n个文档,每个集合中的字段名称列表以及每个字段类型的列表.

Nei*_*eil 3

我选择用 C# 编写示例,因为我更熟悉 C# 驱动程序,并且它是问题上列出的标签。您可以对每个集合运行聚合,以查找每个文档的所有顶级字段及其 (mongodb) 类型。

聚合分 3 个步骤完成。假设输入是 10 个文档,它们都具有以下形式:

{
  "_id": ObjectId("myId"),
  "num": 1,
  "str": "Hello, world!"
}
Run Code Online (Sandbox Code Playgroud)
  1. $projectfieldName将每个文档转换为包含值和的文档数组fieldType。使用单个数组字段输出 10 个文档。数组字段将有 3 个元素。

  2. $unwind字段信息数组。输出 30 个文档,每个文档都有一个字段对应于步骤 1 的输出中的一个元素。

  3. $groupfieldName和 的字段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's 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以迭代结果集:

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}");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)