node.js - Mongoose 选择子文档数小于 X 的记录
问题描述
我有 nodejs/mongodb 和 mongoose 设置。一切都是最后一个版本。
我在 NOSQL 中有点“全新”,并尝试使用 NOSQL 和 mongoose ORM 与这样的 SQL 查询重写:
select * from documents where count(select * from subdocuments where subdocuments.documentId = documents.id) = 5 order by documents.id desc limit 1
在我的情况下(嵌套集合),主要的集合结构是:
documents: [{
_id: ObjectId
subdocuments: [{
_id: ObjectId
}]
}]
documents.findOne
所以我只需要使用mongoose 函数获取最后一个具有 count subdocuments = 5 的对象。
这是否可以使用 mongodb/mongoose 进行所有这些聚合?我找不到任何与我的案子有关的东西。
谢谢!
解决方案
有一个称为运算符$expr
,它允许您在查询语言中使用聚合表达式。这在这里非常方便,您需要在查找查询中使用聚合运算符。
将您的查询分解成块以便理解,让我们进行检查
subdocuments.documentId = documents.id
在 mongo 中,这意味着迭代子文档数组以搜索满足上述条件的子文档,并且可以使用以下方式表示
$filter
:
{
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
}
计数位通常用$size
运算符表示,因此从上面获取结果,此查询
count(select * from subdocuments where subdocuments.documentId = documents.id)
被翻译成表达式
{
'$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
}
}
使用比较运算符$gt
满足条件
where count(select * from subdocuments where subdocuments.documentId = documents.id) > 5
作为
{
'$gt': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
为了平等,用$eq
{
'$eq': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
然后可以将上述内容find()
与 $expr 一起用于查询
db.collection.find({
'$expr': {
'$eq': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
})
排序和限制分别遵循 usingsort()
和limit()
cursor 方法
db.collection.find({
'$expr': {
'$eq': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
}).sort({ '_id': -1 }).limit(1)
此查询也有一个聚合变体。使用聚合框架,管道中使用的表达式是相似的。
查找部分在$match
管道步骤中完成:
db.collection.aggregate([
{ '$match': {
'$expr': {
'$eq': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
} }
])
排序和限制分别在流水线阶段$sort
和$limit
流水线阶段进行
db.collection.aggregate([
{ '$match': {
'$expr': {
'$eq': [
{ '$size': {
'$filter': {
'input': '$subdocuments',
'cond': { '$eq': ['$$this._id', '$_id'] }
}
} },
5
]
}
} },
{ '$sort': { '_id': 1 } },
{ '$limit': 1 }
])
推荐阅读
- excel - VBA:如何找到第一个未隐藏的行
- git - 为什么 .gitignore 和 .metadata 没有被提交?
- angular - 检查Angular 2单元测试用例中函数返回的对象类型
- influxdb-2 - 我可以在 influx db 2 中查询数据库的大小吗
- javascript - 自定义jQuery数据表导出PDF
- python - 如何从蓝牙套接字捕获错误并打印自定义消息?
- version - 如何检查我在 GoogleColab 中使用的软件包版本?
- javascript - 如何通过 vue 路由器将对象作为道具传递
- python - 连续两次调用 cursor.execute() 会产生不一致的结果
- php - 401 Unauthorized 尝试调用谷歌云功能时