使用C#聚合$lookup
我有以下MongoDb查询工作:
db.Entity.aggregate( [ { "$match":{"Id": "12345"} },{ "$lookup": { "from": "OtherCollection","localField": "otherCollectionId","foreignField": "Id","as": "ent" } },{ "$project": { "Name": 1,"Date": 1,"OtherObject": { "$arrayElemAt": [ "$ent",0 ] } } },{ "$sort": { "OtherObject.Profile.Name": 1 } } ] ) 这将检索与另一个集合中的匹配对象连接的对象列表. 有没有人知道如何使用LINQ或使用这个确切的字符串在C#中使用它? 我尝试使用以下代码,但它似乎无法找到QueryDocument和MongoCursor的类型 – 我认为它们已被弃用? BsonDocument document = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{ name : value }"); QueryDocument queryDoc = new QueryDocument(document); MongoCursor toReturn = _connectionCollection.Find(queryDoc); 解决方法
无需解析JSON.这里的所有内容实际上都可以直接使用LINQ或Aggregate Fluent接口完成.
只是使用一些演示类,因为这个问题并没有真正发挥作用. 建立 基本上我们这里有两个系列 实体 { "_id" : ObjectId("5b08ceb40a8a7614c70a5710"),"name" : "A" } { "_id" : ObjectId("5b08ceb40a8a7614c70a5711"),"name" : "B" } 和别的 { "_id" : ObjectId("5b08cef10a8a7614c70a5712"),"entity" : ObjectId("5b08ceb40a8a7614c70a5710"),"name" : "Sub-A" } { "_id" : ObjectId("5b08cefd0a8a7614c70a5713"),"entity" : ObjectId("5b08ceb40a8a7614c70a5711"),"name" : "Sub-B" } 还有几个绑定它们的类,就像非常基本的例子一样: public class Entity { public ObjectId id; public string name { get; set; } } public class Other { public ObjectId id; public ObjectId entity { get; set; } public string name { get; set; } } public class EntityWithOthers { public ObjectId id; public string name { get; set; } public IEnumerable<Other> others; } public class EntityWithOther { public ObjectId id; public string name { get; set; } public Other others; } 查询 流畅的界面 var listNames = new[] { "A","B" }; var query = entities.Aggregate() .Match(p => listNames.Contains(p.name)) .Lookup( foreignCollection: others,localField: e => e.id,foreignField: f => f.entity,@as: (EntityWithOthers eo) => eo.others ) .Project(p => new { p.id,p.name,other = p.others.First() } ) .Sort(new BsonDocument("other.name",-1)) .ToList(); 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A","B" ] } } },{ "$lookup" : { "from" : "others","localField" : "_id","foreignField" : "entity","as" : "others" } },{ "$project" : { "id" : "$_id","name" : "$name","other" : { "$arrayElemAt" : [ "$others",0 ] },"_id" : 0 } },{ "$sort" : { "other.name" : -1 } } ] 可能最容易理解,因为流畅的界面基本上与一般的BSON结构相同. 另一种是 BsonArray subpipeline = new BsonArray(); subpipeline.Add( new BsonDocument("$match",new BsonDocument( "$expr",new BsonDocument( "$eq",new BsonArray { "$$entity","$entity" } ) )) ); var lookup = new BsonDocument("$lookup",new BsonDocument("from","others") .Add("let",new BsonDocument("entity","$_id")) .Add("pipeline",subpipeline) .Add("as","others") ); var query = entities.Aggregate() .Match(p => listNames.Contains(p.name)) .AppendStage<EntityWithOthers>(lookup) .Unwind<EntityWithOthers,EntityWithOther>(p => p.others) .SortByDescending(p => p.others.name) .ToList(); 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A",{ "$lookup" : { "from" : "others","let" : { "entity" : "$_id" },"pipeline" : [ { "$match" : { "$expr" : { "$eq" : [ "$$entity","$entity" ] } } } ],{ "$unwind" : "$others" },{ "$sort" : { "others.name" : -1 } } ] Fluent“Builder”不直接支持语法,LINQ表达式也不支持 除了其他用途之外,“子管道”的主要任务是减少目标数组 可查询的GroupJoin var query = entities.AsQueryable() .Where(p => listNames.Contains(p.name)) .GroupJoin( others.AsQueryable(),p => p.id,o => o.entity,(p,o) => new { p.id,other = o.First() } ) .OrderByDescending(p => p.other.name); 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A","as" : "o" } },{ "$project" : { "id" : "$_id","other" : { "$arrayElemAt" : [ "$o",{ "$sort" : { "other.name" : -1 } } ] 这几乎完全相同,但只是使用不同的接口并产生略微不同的BSON语句,实际上只是因为功能语句中的简化命名.这确实提出了使用从SelectMany()生成的 var query = entities.AsQueryable() .Where(p => listNames.Contains(p.name)) .GroupJoin( others.AsQueryable(),other = o } ) .SelectMany(p => p.other,other) => new { p.id,other }) .OrderByDescending(p => p.other.name); 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A","as" : "o" }},"other" : "$o",{ "$unwind" : "$other" },{ "$project" : { "id" : "$id","other" : "$other","_id" : 0 }},{ "$sort" : { "other.name" : -1 } } ] 通常在 自然的 var query = from p in entities.AsQueryable() where listNames.Contains(p.name) join o in others.AsQueryable() on p.id equals o.entity into joined select new { p.id,other = joined.First() } into p orderby p.other.name descending select p; 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A","as" : "joined" } },"other" : { "$arrayElemAt" : [ "$joined",{ "$sort" : { "other.name" : -1 } } ] 所有这些都非常熟悉,而且实际上只是功能命名.就像使用 var query = from p in entities.AsQueryable() where listNames.Contains(p.name) join o in others.AsQueryable() on p.id equals o.entity into joined from sub_o in joined.DefaultIfEmpty() select new { p.id,other = sub_o } into p orderby p.other.name descending select p; 请求发送到服务器: [ { "$match" : { "name" : { "$in" : [ "A",{ "$unwind" : { "path" : "$joined","preserveNullAndEmptyArrays" : true } },"other" : "$joined",{ "$sort" : { "other.name" : -1 } } ] 实际上使用的是“optimized coalescence”表格.翻译仍然坚持添加 摘要 因此,有很多方法可以基本上达到基本相同的查询语句,结果完全相同.虽然您“可以”将JSON解析为BsonDocument表单并将其提供给流畅的Aggregate()命令,但通常最好使用自然构建器或LINQ接口,因为它们可以轻松映射到同一语句. 显示 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |