首页 > 解决方案 > 展开时字段名称冲突 (_id)

问题描述

我有 mongo 集合,其中的文档如下所示:

{ 
  _id: "384iojweiu83ur8233uui",
  name: "Jack",
  friends: [
    { 
      _id: "384798237498234",
      name: "Alfred"
    },
    { 
      _id: "384798234749829",
      name: "Deborah"
    }
  ]
}

我想检索一个给定它的人_id,并且只有一个给定朋友的朋友_id。像这样的东西:

{ 
  _id: "384iojweiu83ur8233uui",
  name: "Jack",
  friend_id: "384798237498234",
  friend_name: "Alfred"  
}

我试图通过 c# mongo 驱动程序中的方法来做到unwind这一点,但是我被困在这一点上。

var people = await collection.Aggregate()
    .Unwind<Person, PersonWithFriend>(_ => _.friends } )
    .Match( _ => _.Id == new ObjectId("5b646004b5728100042dd358"))
    .ToListAsync(); 

标签: c#mongodbsubqueryaggregation

解决方案


您可以使用位置运算符$仅返回数组的第一个匹配元素:

db.users.find(
    { "friends._id": "384798237498234" },
    { "name": 1, "friends.$": 1 }
);

或者,如果您需要匹配friends子文档上的多个条件,您可以使用$elemMatch

db.users.find(
    { "friends":  { 
        "$elemMatch": { "id": "384798237498234",  "somethingElse": "..." }
    }},
    { "name": 1, "friends.$": 1 }
);

friends这将使用具有单个元素的数组生成结果:

{ 
    _id: "384iojweiu83ur8233uui",
    name: "Jack",
    friends: [{
        id: "384798237498234",
        name: "Alfred"  
    }]
}

如果您确实需要在结果对象的根目录中包含朋友的id和,那么您可以使用聚合框架做同样的事情,并在最后添加一个展开步骤。name

在 C# 中应该是这样的:

users
    .Find(user => user.friends.Any(friend => friend.id == "384798237498234"))
    .Project(projection)
    .ToListAsync();

推荐阅读