2016-08-18 32 views
0

我想用C#.Net來查詢MongoDB集合。我想根據一些標準過濾集合,然後只投影某些字段,然後將投影轉換爲鍵值對。如何將mongo文檔轉換爲.Net中的鍵值對?

我能夠過濾和項目我想要的方式。不過,我想知道是否有構建的方法將投影轉換爲鍵值對?

這裏是我的蒙戈DB文件看起來像

{ 
    "_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); 

     } 
+0

你能告訴我們到底是什麼鍵(S)和值(S)你想結束了?您可能可以做一個更復雜的投影,以避免必須遍歷返回的bson。 –

+0

@VinceBowdren在下面看到我的答案。我使用遞歸方法來填充字典。我正在處理的mongo文件沒有固定的模式 – LP13

回答

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; 
    } 
}); 
+0

我沒有看到fuent接口'IFindFluent '有ToDictionary()方法,除非它的某些其他命名空間中的extenstion方法。還要注意''context'元素有分層結構 – LP13

+0

啊!正確。您需要ToEnumerable()或ToList()或(await ToListAsync())ToDictionary是IEnumerable上的一種方法 Joe

+0

感謝您的快速響應。我仍然對ToDictionary(..)方法中的內容感到困惑。 'document.ToEnumerable()。ToDictionary(這裏是什麼?);'請注意,我沒有架構,我正在使用BsonDocument – LP13

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); 
      } 
     } 
    }