首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >猫鼬方案设计多到多

猫鼬方案设计多到多
EN

Stack Overflow用户
提问于 2019-01-18 14:34:54
回答 1查看 103关注 0票数 0

我正在尝试为一个任务管理应用程序设计一个猫鼬方案架构/设计。

期望的功能和模型:

型号:

  • 用户拥有板
  • 董事会-有名单
  • 清单-有卡片
  • 卡片

功能:

  • 用户可以创建一个板
  • 用户可以在板中创建列表。
  • 用户可以在列表中创建卡片。
  • 用户可以将成员添加到董事会。
  • 用户可以从董事会成员中将成员添加到卡片中。
  • 用户可以删除板,删除所有列表和卡片,并删除成员。
  • 用户可以删除列表,删除列表中的所有卡片。
  • 用户可以删除卡,从卡中删除所有成员。
  • 用户可以更新面板中的列表位置(排序)。
  • 用户可以更新卡在列表中的位置(排序)
  • 附加功能(可选)
代码语言:javascript
复制
- User can add comments to the card
- Card activity logging (On move, on edit, on comment)

我知道它有很多要问的问题,但是如何设计这种功能的方案呢?

孩子父母的引用会是最好的解决方案吗?

例如。

用户:

代码语言:javascript
复制
{
 name: 'Bob',
 _id: '2626'
}

董事会:

代码语言:javascript
复制
{
 name: 'Board name',
 _id: '123456',
 members: [
  { type: ObjectID, ref: 'user' } // '2626'
 ]
}

列表:

代码语言:javascript
复制
{
 name: 'List name',
 _id: '2525',
 boardId: { type: ObjectID, ref: 'board' } // '123456'
}

卡:

代码语言:javascript
复制
{
 name: 'Card name',
 boardId: { type: ObjectID, ref: 'board' } // '123456',
 listId: { type: ObjectID, ref: 'list' } // '2525'
}

我该如何查询这种结构呢?

  • 1)按用户id获取板的列表
  • 2)按板id获取列表
  • 3)按棋盘id和listid获取一张卡片列表

因此,对于董事会的观点,我会去抓取所有的名单,但我将不得不去为每个名单的所有卡片,似乎没有真正的效率。

也许,当进入板视图时,我应该只通过板id查询卡片,但是如何获得列表,并将每一张卡放入自己的列表中?

如何处理删除卡片或将卡片从一个列表移到另一个列表?

别对我太苛刻了,我对mongodb世界很陌生,但我真的在尽我最大的努力。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-21 13:44:04

您定义的模式非常好,如下所示。

最初,当用户登录时,您需要向他们展示板的列表。这应该很容易,因为您只需对板集合上的user_id进行查找查询。

代码语言:javascript
复制
Board.find({members: user_id}) // where user_id is the ID of the user

现在,当用户单击特定的面板时,您可以使用board_id获取列表,类似于上面的查询。

代码语言:javascript
复制
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}) //其中board_id是董事会的ID,listId是列表的Id

现在,让我们看一看可能同时需要来自2个或更多集合的数据的情况。例如,当用户点击板上时,您不仅需要董事会中的列表,而且还需要该板中的卡片。在这种情况下,您需要编写这样的聚合,

代码语言:javascript
复制
            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'
                }
            }
        ])

这将返回板,在每个板中,将有一系列与该板相关联的列表。如果一个特定的板没有一个列表,那么它就会有一个空数组。

类似地,如果要将卡片添加到列表和板中,聚合查询将是一个更复杂的机器人,因此,

代码语言:javascript
复制
            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'
                }
            }
        ])

这将增加一组卡片以及混合。同样,您也可以获得列表的卡片。

现在,让我们考虑一下这是否是最好的模式。我个人认为您建议的模式非常好,因为另一种方法是在父集合中存储ID,这将允许您使用填充来获取数据,而不是查找查询。

例如,将列表in存储在板集合中。这样做的缺点是,每当添加新列表时,您都需要在列表集合中添加该列表,并更新列表连接到的板(添加列表ID),我认为这太繁琐了。

最后,关于您给出的模式的一些建议,我认为您应该在每个集合中添加user_id (创建者ID),因为在许多情况下,您需要显示创建特定板或列表的用户的名称或其他任何东西,而且由于您具有将用户添加到特定卡的功能,我认为您应该有两个字段,一个是creator_id,另一个应该是associated_users,它将是一个数组(显然您可以选择更好的名称)。

应在卡片和其他要按位置排序的集合中添加“位置”字段。这个字段应该是一个数字。

删除一张卡片或将它从一个列表移到另一个列表应该是相当容易的,并且到目前为止应该是不言自明的。

编辑1:基于注释

你不需要在聚合之后给列表分配卡片,你可以在你的聚合本身中这样做,所以它会是这样的,

代码语言:javascript
复制
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'
        }
    },
    // unwind lists (because it's an array at the moment)
    {
        $unwind: '$lists'
    },
    // Now you have object named lists in every board object
    // get cards that match the list_id (note that the cards contain list_id)
    {
        $lookup:
        {
            from: 'card',
            localField: '_id',
            foreignField: 'listId',
            as: 'cards'
        }
    },
    // now merge back the objects and get a simple object for each boardID
    {
        $group: {
            _id: "$_id",
            members: { $addToSet: "$members" },
            lists: { $addToSet: "$lists" }
        }
    }
])

这会给你这样的东西,

代码语言:javascript
复制
data = {
    '_id': '123456',
    'members': [
        {
            name: 'Bob',
            _id: '2626'
        },
        {
            name: 'Matthew',
            _id: '2627'
        }
    ],
    'lists': [
        {
            name: 'List 1',
            _id: '2525',
            boardId: '123456',
            cards: [
                {
                    name: 'Card 1',
                    boardId: '123456',
                    listId: '2525'
                },
                {
                    name: 'Card 2',
                    boardId: '123456',
                    listId: '2525'
                }
            ]
        },
        {
            name: 'List 2',
            _id: '2526',
            boardId: '123456',
            cards: [
                {
                    name: 'Card 3',
                    boardId: '123456',
                    listId: '2525'
                },
                {
                    name: 'Card 4',
                    boardId: '123456',
                    listId: '2525'
                }
            ]
        }
    ]
}

因此,基本上,您可以在一个查询本身中获得列表和这些列表的卡片,这是非常有效的。

接下来是你问的两个问题,

  1. 卡片从一个列表移动到另一个列表,只需将卡片文档中的listId字段编辑到新的listID (实际上非常简单)。
  2. 卡在列表中向上移动一个位置

正如我所说的,如果您想要这个职位,您需要在文档中添加一个名为position的字段,然后无论何时移动卡片,您都需要更改这些卡片的“位置”的值。在聚合过程中,只需添加另一个名为“$sort”的阶段,并根据位置值对其进行排序。这将是有点乏味,因为无论何时你移动一张卡,你需要更新的位置,上面的卡。

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

https://stackoverflow.com/questions/54256090

复制
相关文章

相似问题

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