如何在.Net中将mongo文档转换为键值对?

时间:2016-08-18 17:48:19

标签: c# .net json mongodb

我正在尝试使用C#.Net查询MongoDB集合。我想根据某些条件过滤集合,然后只投影某些字段,然后将投影转换为键值对。

我能够以我想要的方式过滤和投射。但是我想知道是否有内置方法将投影转换为键值对?

以下是我的mongo数据库文档的样子

{
    "_id" : 32178271832,
    "url" : "www.somedomain.com",
    "fileName" : "somefilename.pdf",
    "isDone" : true,
    "client" : ObjectId("56g2e67d7gf2208c2dbe33yt"),
    "startTime" : ISODate("2015-05-23T18:50:11.271Z"),
    "endTime" : ISODate("2015-05-23T18:52:43.819Z"),
    "cost" : 30,
    "taskGroups" : [ 
        {
            "phase" : "phase1",
            "name" : "Some Name",    
            "_id" : ObjectId("43r2e46h7er2208c2geh74e5"),
            "tasks" : [ 
                {
                    "_id" : ObjectId("43r2e46h7er2208c2geh74e5"),
                    "input" : [],                 
                    "predecessors" : []
                }
            ]
        }        
    ],
    "context" : {
        "startTime" : ISODate("2016-03-23T18:50:11.271Z"),
        "endTime" : ISODate("2016-03-23T18:52:43.819Z"),
        "state" : "GA",       
        "PHASE1" : {
            "hasaccountnumber" : "Yes",
            "accountnumber" : 1
            "Child1":{
                "Property1": "SomeValue1"
                "Property2" : "SomeValue2"
            }
        }        
    }
}

这是我的代码

public static IDictionary<string,string> GetFromMongo()
    {
        var collection = _mongodb.GetCollection<BsonDocument>("kunits");
        var filterBuilder = Builders<BsonDocument>.Filter;
        var filter = filterBuilder.Eq<bool>("isDone", true) & filterBuilder.Exists("isTransformed", false);

        var projection = Builders<BsonDocument>.Projection
            .Include("client")
            .Include("url")
            .Include("fileName")
            .Include("context");

        var document = collection.Find(filter).Project(projection).FirstOrDefault();

        IDictionary<string,string> dictionary = ??

        return dictionary;
    }

无论如何将文档转换为字典?该文档具有层次结构。

UPDATE2
所以这就是我所做的。但是,如果BsonValue是JSON,我如何递归处理?例如,在上面的JSON context元素具有层次结构的情况下,如何递归循环并在字典中添加其每个字段?

         var document = collection.Find(filter).Project(projection).FirstOrDefault();
        var docs = new Dictionary<string, BsonValue>();
        foreach (var elm in document.Elements)
        {
            //how to recursively process when elm.value is JSON ??

            docs.Add(elm.Name, elm.Value);

        }

2 个答案:

答案 0 :(得分:1)

我不相信FirstOrDefault()在投影上是正确的。有一个ToDictionary方法可以映射你想要的东西:

var document = collection.Find(filter).Project(projection);
var dictionary = documents.ToEnumerable().ToDictionary(key => key.client, value => value.url);

一种不同的方法

var docs = new Dictionary<string, BsonDocument>();
var result = collection.Find(filter).Project(projection);      
result.ForEachAsync((bsonDoc) =>
{
    string name = bsonDoc.GetValue("[Your Dictionary Key]").AsString;
    if (!docs.ContainsKey(name))
    {
        docs[name] = bsonDoc;
    }
});

答案 1 :(得分:0)

终于得到它BsonValue拥有属性IsBsonDocument。我们可以检查以确定vaue是JSON还是原始数据类型。然后递归循环

public static Dictionary<string, BsonValue> GetFromMongo()
    {
        var collection = _mongodb.GetCollection<BsonDocument>("units");
        var filterBuilder = Builders<BsonDocument>.Filter;
        var filter = filterBuilder.Eq<bool>("isDone", true) & filterBuilder.Exists("isTransformed", false);

        var projection = Builders<BsonDocument>.Projection
            .Include("client")
            .Include("url")
            .Include("fileName")
            .Include("context");

        var document = collection.Find(filter).Project(projection).FirstOrDefault();
        var dictionary = new Dictionary<string, BsonValue>();
        Recurse(document, dictionary);
        return dictionary;
    }

    private static void Recurse(BsonDocument doc, Dictionary<string, BsonValue> dictionary)
    {
        foreach (var elm in doc.Elements)
        {
            if (!elm.Value.IsBsonDocument)
            {
                if (!dictionary.ContainsKey(elm.Name))
                {
                    dictionary.Add(elm.Name, elm.Value);
                }
            }
            else
            {
                Recurse((elm.Value as BsonDocument), dictionary);
            }
        }
    }