使用 Linq 进行 MongoDB 联接

Aja*_*Aju 4 linq asp.net-mvc mongodb asp.net-core-mvc mongodb-csharp-2.0

CommentCollection
{
   "_id":"5b63f0f23846b70011330889",
   "CommentType":"task",
   "EntityReferenceId":"6082ef25-6f9a-4874-a832-f72e0f693409",
   "CommentLink":null,
   "EntityName":"task2",
   "participants":[
                  ObjectId("52ffc4a5d85242602e000000"),
                  ObjectId("52ffc4a5d85242602e000001")    
 ],
"Threads":[
  {
     "_id":"69bcef71-3695-4340-bdec-4a6e4c58c490",
     "CommentType":"task",
     "UserId":ObjectId("52ffc4a5d85242602e000000"),         
     "CommentByUserType":"Admin",
     "EntityReferenceId":"6082ef25-6f9a-4874-a832-f72e0f693409",
     "Content":"fdffd",
     "ProjectName":null,
     "PostedDate":"2018-08-03T13:03:05.939Z",
     "Active":true,
     "Attachment":[

     ]
  }
Run Code Online (Sandbox Code Playgroud)

另一个集合是

userCollection
{  
     "Id":ObjectId("52ffc4a5d85242602e000000"),
     "Name":"Pms Admin",
     "Email":"pms@xtrastaff.com",
     "Type":"Admin",
     "UserId":"6082ef25-6f9a-4874-a832-f72e0f693409",
     "UserImage":"6082ef25-6f9a-4874-a832-f72e0f693409"  
}
Run Code Online (Sandbox Code Playgroud)

CommentCollection中有一个“参与者”数组,它存储用户的 id(来自用户集合)。

我的要求是加入这两个集合以获取我的 asp.net core 项目(Linq)中的用户详细信息。参与者包含 id 列表

mic*_*ckl 7

在 Mongo shell 中,您将使用$lookup,它可以在数组上使用,如例所示,您的查询可能如下所示:

db.Comment.aggregate([
    {
        $lookup: {
            from: "user",
            localField: "participants",
            foreignField: "Id",
            as: "participants"
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

它只是用第二个集合中的对象数组替换参与者:

{
    "_id" : "5b63f0f23846b70011330889",
    "CommentType" : "task",
    "EntityReferenceId" : "6082ef25-6f9a-4874-a832-f72e0f693409",
    "CommentLink" : null,
    "EntityName" : "task2",
    "participants" : [
        {
            "_id" : ObjectId("5b6e875b9d52833fbe9879c2"),
            "Id" : ObjectId("52ffc4a5d85242602e000000"),
            "Name" : "Pms Admin",
            "Email" : "pms@xtrastaff.com",
            "Type" : "Admin",
            "UserId" : "6082ef25-6f9a-4874-a832-f72e0f693409",
            "UserImage" : "6082ef25-6f9a-4874-a832-f72e0f693409"
        }
    ],
    "Threads" : //...
}
Run Code Online (Sandbox Code Playgroud)

在 C# 中,您可以使用Lookup语法来表达这一点。第一个选项允许您获取类型列表,BsonDocument该列表只是跳过类型检查:

var collection = db.GetCollection<Comment>("Comment"); 
List<BsonDocument> result = collection.Aggregate()
                       .Lookup("user", "participants", "Id", "participants")
                       .ToList();
Run Code Online (Sandbox Code Playgroud)

此处不能使用常规 LINQ 的原因join是,实际上您正在将数组与标量值进行比较(这应该是equalsjoin 的一部分)。但是,如果您需要强类型结果,则BsonDocuments可以使用不同版本的Lookup方法,该方法采用类型和表达式而不是字符串。因此,您需要另一个类来$lookup获取结果,可以使用继承来解决:

public class Comment
{
    public string _id { get; set; }
    public string CommentType { get; set; }
    public string EntityReferenceId { get; set; }
    public string CommentLink { get; set; }
    public string EntityName { get; set; }
    public ObjectId[] participants { get; set; }
    public Thread[] Threads { get; set; }
}

public class CommentWithUsers : Comment
{
    public User[] Users { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以获得一个列表CommentWithUser

var comments = mydb.GetCollection<Comment>("Comment");
var users = mydb.GetCollection<User>("user");

List<CommentWithUser> result = comments.Aggregate()
                                       .Lookup<Comment, User, CommentWithUsers>(
                                            users, 
                                            x => x.participants, 
                                            x => x.Id, 
                                            x => x.Users).ToList();
Run Code Online (Sandbox Code Playgroud)