首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >猫鼬巢式(2级)

猫鼬巢式(2级)
EN

Stack Overflow用户
提问于 2018-05-03 11:42:25
回答 2查看 981关注 0票数 0

我试图使用CASL对嵌套项进行授权检查。它使用猫鼬来查询数据和检查访问。

我的领域是:

  • 一个“使用者”可以拥有更多的“车辆”。
  • “文件”必须有车辆

模式:

代码语言:javascript
复制
vehicle { users: [ {type: objectId, ref: 'user'} ] }
document { vehicle: {type: objectId, ref: 'vehicle' }}

若要“按用户”查找车辆,我会:

代码语言:javascript
复制
db.getCollection('vehicle').find(
    { users: {$in: [ ObjectId("5ae1a957d67500018efa2c9d") ]} }
)

这是可行的。

在文件收集中,数据具有如下记录:

代码语言:javascript
复制
{
    "_id": ObjectId("5aeaad1277e8a6009842564d"),
    "vehicle": ObjectId("5aea338b82d8170096b52ce9"),
    "company": "Allianz",
    "price": 500,
    "date_start": ISODate("2018-05-02T22:00:00.000Z"),
    "date_end": ISODate("2019-05-02T22:00:00.000Z"),
    "createdAt": ISODate("2018-05-03T06:32:50.590Z"),
    "updatedAt": ISODate("2018-05-03T06:32:50.590Z"),
    "__v": 0
}

要查找“用户”文档,我需要:

代码语言:javascript
复制
db.getCollection('document').find(
    { "vehicle.users": {$in: [ ObjectId("5ae1a957d67500018efa2c9d") ]} }
)

它不起作用。是否有可能在一个单一的“查找”查询中做到这一点?

EN

回答 2

Stack Overflow用户

发布于 2018-05-03 18:18:41

您不能在简单的MongoDB 查找()查询中这样做,因为有关车辆用户的数据存在于车辆集合中,而不是文档集合中。

但是,使用聚集管线可以使用$lookup操作符将数据链接到两个不同的集合中。聚合应该是这样的:

代码语言:javascript
复制
db.document.aggregate([
  {$lookup: {
    "from": "vehicle",
    "localField": "vehicle",
    "foreignField": "_id",
    "as": "vehicleDetails",
  }},
  {$match: {"vehicleDetails.users" : ObjectId("5ae1a957d67500018efa2c9d")}}
])

您可能需要添加更多的阶段来按照您需要的方式重新构造数据,但关键是使用$lookup链接来自两个集合的数据,然后使用$match过滤结果集。

票数 1
EN

Stack Overflow用户

发布于 2018-06-05 10:52:44

为了使此查询工作,需要将users In数组存储在vehicle文档中。Mongo和CASL都不会自动管理外部引用。

替代解决方案

所以,我看不出什么方法:

  1. 在定义规则时检索所有车辆的ids。如果车辆数量不多,这是很好的(<= 1000)。
代码语言:javascript
复制
const vehicleIds = await getVehicleIds(user)

can(['read', 'update'], 'document', { vehicle: { $in: vehicleIds } })
  1. 破坏你的计划。例如,将附加的user_id字段添加到车辆文档中
  2. 想想是否可以将文档作为子文档嵌入到向量中,如下所示:
代码语言:javascript
复制
vehicle {
  documents: [Document],
  users: [ {type: objectId, ref: 'user'} ]
}
  1. 只是不要定义每个文档的规则,并在路由上强制它们(REST或GraphQL并不重要)。
代码语言:javascript
复制
app.get('/vehicle/:id/documents', async (req, res) => {
  const vehicle = await Vehicle.findById(req.params.id)

  req.ability.throwUnlessCan('read', vehicle)
  const documents = Document.find({ vehicle: vehicle.id })

  res.send({ documents })
})
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50154241

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档