我正在创建一个非常基本的功能看板。
到目前为止,我的董事会有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拖放库制作的。
我想找到最好的方法来渲染带有列表(列)和卡片的木板。
据我了解,我应该首先通过Members数组中的用户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'
]
}
我尝试了什么?
到目前为止我只想出一件事,那就是:
但是用这种方式看来,我的列表仅需要一个用于前端卡到列表的ID排序的空数组cards: []
,这似乎是错误的。
这是个好方法吗?还是应该重新设计模型和架构并采用其他方式?任何帮助将不胜感激!
答案 0 :(得分: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'
}
}
])
这还将在混合中添加一系列纸牌。同样,您也可以获取列表中的卡片。
答案 1 :(得分:1)
回答得有点晚,但是我认为它仍然可以帮助某人。使用聚合框架可以解决您遇到的问题。尽管另一个答案提到了一个很好的方法,但是它仍然没有嵌入卡片数据。
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',
},
},
]);
这会将卡片作为数组包含在每个列表中。