Mongoose/Mongodb 类似 trello 的基本方案问题,在 vue 中呈现
Posted
技术标签:
【中文标题】Mongoose/Mongodb 类似 trello 的基本方案问题,在 vue 中呈现【英文标题】:Mongoose/Mongodb basic trello like scheme problem with rendering in vue 【发布时间】:2019-06-30 04:55:50 【问题描述】:我正在创建一个非常基本的功能看板。
到目前为止,我的板子有 4 个模型:
用户模型
var userSchema = new Schema(
name:
type: String,
required: true
)
module.exports = mongoose.model('User', userSchema)
板模型
var boardSchema = new Schema(
title:
type: String,
required: true
,
lists: [ listSchema ]
members: [
type: Schema.Types.ObjectId,
ref: 'user'
]
);
module.exports = mongoose.model('Board', boardSchema)
列表架构
let listSchema = new Schema(
title:
type: String,
required: true
,
userCreated:
type: Schema.Types.ObjectId,
required: true,
ref: 'user'
,
boardId:
type: Schema.Types.ObjectId,
required: true,
ref: 'board'
,
sort:
type: Number,
decimal: true,
required: true
)
module.exports = mongoose.model('List', listSchema)
卡片架构
var cardSchema = new Schema(
title:
type: String,
required: true
,
description:
type: String
,
boardId:
type: Schema.Types.ObjectId,
required: true,
ref: 'board'
,
listId:
type: Schema.Types.ObjectId,
required: true,
ref: 'list'
,
members: [
type: Schema.Types.ObjectId,
ref: 'user'
],
sort:
type: Number,
decimal: true,
required: true
)
module.exports = mongoose.model('Card', cardSchema)
我在寻找什么?
我的前端是用 Vue.js 和 sortable.js 拖放库制作的。
我想找到用列表(列)和卡片在其中呈现板的最佳方法。
据我了解,我应该首先通过成员数组中的用户 ID 获取我的董事会。
然后我的板子已经嵌入了列表。
在第二个 api 请求中,我通过 boardId 获取所有卡片。
我的问题是 - 我如何正确地将所有卡片放入/渲染到每个拥有列表中?
所以最后我想要这样的东西:
title: 'My board',
lists: [
title: 'My list',
_id: '35jj3j532jj'
cards: [
title: 'my card',
listId: '35jj3j532jj'
]
,
title: 'My list 2',
_id: '4gfdg5454dfg'
cards: [
title: 'my card 22',
listId: '4gfdg5454dfg'
,
title: 'my card 22',
listId: '4gfdg5454dfg'
]
]
members: [
'df76g7gh7gf86889gf989fdg'
]
我尝试了什么?
到目前为止,我只想到了一件事,那就是:
-
挂载钩子中的两个 api 调用 - 一个用于获取带有列表的板,第二个用于获取所有卡片。
然后我循环槽列表和循环槽卡并按 id 将每张卡推入列表?
但这样看来,我的列表似乎需要一个名为 cards: []
的空数组,仅用于按 id 进行前端卡片到列表排序,这似乎有些错误。
这是个好方法吗?或者我应该重新设计我的模型和模式并采用其他方式吗?任何帮助将不胜感激!
【问题讨论】:
这听起来很像卡片和列表属于板,对吧?我知道这看起来很奇怪,但您可以将其更新为具有Lists
和 Cards
的单个 Board
集合。如果你只想要一个列表,你可以使用投影来限制返回的文档。对于 mongo,“属于”一般意味着您应该强烈考虑使用嵌套文档。
【参考方案1】:
您定义的架构非常好,不过只是进行了一次修改。
Board 模型中不需要有“列表”,因为它已经在列表中可用,而且如果您将其保留在 Board 中,那么每次添加新列表时,您也需要编辑 Board。
流程如下。
最初,当用户登录时,您需要向他们显示板列表。这应该很容易,因为您只需使用 board 集合上的 user_id 进行查找查询。
Board.find(members: user_id) // where user_id is the ID of the user
现在当用户点击特定的板子时,您可以获取带有 board_id 的列表,类似于上面的查询。
List.find(boardId: board_id) // where board_id is the ID of the board
同样,您可以借助 list_id 和 board_id 获得卡片。
Card.find(boardId: board_id, listId: list_id) // where board_id is the ID of the board and listId is the Id of the list
现在,让我们看看您可能同时需要来自 2 个或更多集合的数据的情况。例如,当用户点击板时,您不仅需要板中的列表,还需要板中的卡片。在这种情况下,您需要编写这样的聚合,
Board.aggregate([
// get boards which match a particular user_id
$match: members: user_id
,
// get lists that match the board_id
$lookup:
from: 'list',
localField: '_id',
foreignField: 'boardId',
as: 'lists'
])
这将返回棋盘,在每个棋盘中,都会有一个与该棋盘关联的列表数组。如果一个特定的板没有列表,那么它将有一个空数组。
同样,如果您想将卡片添加到列表和板中,聚合查询将是一个更复杂的机器人,因此,
Board.aggregate([
// get boards which match a particular user_id
$match: members: user_id
,
// get lists that match the board_id
$lookup:
from: 'list',
localField: '_id',
foreignField: 'boardId',
as: 'lists'
,
// get cards that match the board_id
$lookup:
from: 'card',
localField: '_id',
foreignField: 'boardId',
as: 'cards'
])
这也将添加一系列卡片。同样,您也可以获取列表卡片。
【讨论】:
【参考方案2】:答案有点晚,但我认为它会帮助某人。您遇到的问题可以使用聚合框架来解决。虽然另一个答案提到了一个很好的方法,但它仍然没有嵌入卡片数据。
MongoDB 文档展示了一种嵌套聚合查询的方法。 Nested Lookup
您的问题可以使用类似的方法。
Board.aggregate([
$match: _id: mongoose.Types.ObjectId(boardId) ,
,
$lookup:
from: 'lists',
let: boardId: '$_id' ,
pipeline: [
$match: $expr: $eq: ['$boardId', '$$boardId'] ,
$lookup:
from: 'cards',
let: listId: '$_id' ,
pipeline: [ $match: $expr: $eq: ['$listId', '$$listId'] ],
as: 'cards',
,
,
],
as: 'lists',
,
,
]);
这会将卡片作为数组包含在每个列表中。
【讨论】:
以上是关于Mongoose/Mongodb 类似 trello 的基本方案问题,在 vue 中呈现的主要内容,如果未能解决你的问题,请参考以下文章
mongoose \ mongodb 按一些列表排序? [复制]
Mongoose/MongoDb 收到错误 geoNear 不是函数