MongoDB 聚合与特定字段不匹配
Posted
技术标签:
【中文标题】MongoDB 聚合与特定字段不匹配【英文标题】:MongoDB Aggregate is not matching specific field 【发布时间】:2021-04-07 13:54:43 【问题描述】:我是 MongoDB 中 Aggregation
的新手,我试图通过举例来理解它的概念。
我正在尝试使用聚合对子文档进行分页,但返回的文档始终是所有文档特定字段的整体值。
我想对包含对象 ID 数组的 following
字段进行分页。
我有这个用户架构:
const UserSchema = new mongoose.Schema(
username:
type: String,
unique: true,
required: true
,
firstname: String,
lastname: String,
following: [
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
],
...
, timestamps: true, toJSON: virtuals: true , toObject: getters: true, virtuals: true );
没有聚合,我可以分页following
,
我有这条路线可以通过username
获取用户的帖子
router.get(
'/v1/:username/following',
isAuthenticated,
async (req, res, next) =>
try
const username = req.params;
const offset: off = req.query;
let offset = 0;
if (typeof off !== undefined && !isNaN(off)) offset = parseInt(off);
const limit = 2;
const skip = offset * limit;
const user = await User
.findOne( username )
.populate(
path: 'following',
select: 'profilePicture username fullname',
options:
skip,
limit,
)
res.status(200).send(user.following);
catch (e)
console.log(e);
res.status(500).send(e)
);
我使用聚合的分页版本:
const following = await User.aggregate([
$match: username
,
$lookup:
'from': User.collection.name,
'let': 'following': '$following' ,
'pipeline': [
$project:
'fullname': 1,
'username': 1,
'profilePicture': 1
],
'as': 'following'
,
,
$project:
'_id': 0,
'following':
$slice: ['$following', skip, limit]
]);
假设我有这些文件:
[
_id: '5fdgffdgfdgdsfsdfsf',
username: 'gagi',
following: []
,
_id: '5fgjhkljvlkdsjfsldkf',
username: 'kuku',
following: []
,
_id: '76jghkdfhasjhfsdkf',
username: 'john',
following: ['5fdgffdgfdgdsfsdfsf', '5fgjhkljvlkdsjfsldkf']
,
]
当我为用户 john:/john/following
测试我的路线时,一切都很好,但是当我测试没有任何以下内容的不同用户时:/gagi/following
,返回的结果与 john 的以下聚合相同似乎与用户名不匹配。
/john/following
|以下:2
/kuku/following
|以下:0
汇总结果:
[
_id: '5fdgffdgfdgdsfsdfsf',
username: 'kuku',
...
,
_id: '5fgjhkljvlkdsjfsldkf',
username: 'gagi',
...
]
我希望/kuku/following
返回一个空数组 [] 但结果与 john 的相同。实际上,我测试的所有用户名都返回相同的结果。
我认为我的实现一定有问题,因为我才开始探索聚合。
【问题讨论】:
【参考方案1】:Mongoose 使用DBRef 能够在检索到该字段后填充该字段。 DBRefs 只在客户端处理,MongoDB 聚合没有任何操作符来处理这些。
聚合管道返回所有用户的原因是查找的管道没有匹配阶段,因此集合中的所有文档都被选中并包含在查找中。
那里的示例文档显示了一个字符串数组而不是 DBRefs,这不适用于populate
。
基本上,您必须决定是要使用聚合还是填充来处理连接。
对于填充,请使用 ref
,如示例架构中所示。
对于聚合,存储一个 ObjectId 数组,以便您可以使用查找链接到 _id
字段。
【讨论】:
啊。知道了。所以管道确实没有执行匹配,但是可以在管道中添加 $match 阶段吗?我使用的IDs
只是为了演示而随机输入的字符,但它们在我的代码中是真正的 ObjectID,并且可以完美地填充并且无需聚合即可进行分页。只是试图通过使用聚合进行分页来理解聚合。
如果它适用于populate
,则该字段包含DBRef
s 而不是ObjectId
s,因此它不适用于聚合
所以我必须将每个用户的 _id 设置为 ObjectID 之类的 "_id": "$oid": "5feec0f2cce7f8b1105142e4"
以便在这种情况下进行聚合?
啊,明白了。现在一切都说得通了。以前不知道 DBRef 和 Manual ref 的东西。感谢您清理一切。以上是关于MongoDB 聚合与特定字段不匹配的主要内容,如果未能解决你的问题,请参考以下文章