Mongoose / Mongodb基本trello之类的方案问题与Vue中的渲染

时间:2019-02-06 09:25:16

标签: javascript node.js mongodb vue.js drag-and-drop

我正在创建一个非常基本的功能看板。

到目前为止,我的董事会有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'
  ]
}

我尝试了什么?

到目前为止我只想出一件事,那就是:

  1. 已挂接的钩子中有两个api调用-一个用于获取带有列表的面板,第二个用于获取所有卡。
  2. 然后我循环搜索槽列表并循环搜索槽卡,然后按ID将每个卡推入列表中?

但是用这种方式看来,我的列表仅需要一个用于前端卡到列表的ID排序的空数组cards: [],这似乎是错误的。

这是个好方法吗?还是应该重新设计模型和架构并采用其他方式?任何帮助将不胜感激!

2 个答案:

答案 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',
    },
  },
]);

这会将卡片作为数组包含在每个列表中。