【问题标题】:Parse Server, MongoDB - get "liked" state of an objectParse Server, MongoDB - 获取对象的“喜欢”状态
【发布时间】:2018-06-23 05:49:06
【问题描述】:

我正在使用在 MongoDB 上运行的 Parse Server。

假设我有集合 UserComment 以及用户和评论的连接表。 用户可以点赞评论,这会在连接表中创建一条新记录。

特别是在 Parse Server 中,可以使用集合中的“关系”字段来定义连接表。

现在,当我想检索所有 cmets 时,我还需要知道它们中的每一个是否都被当前用户喜欢。如何在不进行额外查询的情况下做到这一点?

您可能会说我可以在Comment 表中创建一个数组字段likers 并使用$elemMatch,但这似乎不是一个好主意,因为可能会有成千上万的评论点赞。

我的想法,但我希望有更好的解决方案:

我可以在Comment 表中创建一个数组字段someLikers、一个关系(连接表)字段allLikers 和一个数字字段likesCount。然后将前 100 个喜欢的人放在 someLikersallLikers 中,其他喜欢的人只放在 allLikers 中。我总是会增加likesCount

然后在查询 cmets 列表时,我将使用$elemMatch 实现调用,这将告诉我当前用户是否在someLikers 内。当我得到 cmets 时,我会检查一些 cmets 是否有 likesCount > 100$elemMatch 返回 null。如果是这样,我将不得不在连接表中运行另一个查询,查找这些 cmets 并检查(查询)它们是否被当前用户喜欢。

有更好的选择吗?

谢谢!

【问题讨论】:

  • 你不需要创建连接表,你需要关系和动态创建统计等
  • 看起来您正在使用 MongoDB 的 API ($elemMatch) 来查询您的数据...您有什么理由不使用 Parse 查询吗?
  • @dr_barto 因为我需要知道,在 Find 查询中,用户是否在 likers 数组中,而不选择整个数组。 Parse 似乎不支持这一点,但我还没有尝试使用 Mongo API 来实现它,这只是一个想法。 “$elemMatch 运算符将查询结果中的 字段的内容限制为仅包含与 $elemMatch 条件匹配的第一个元素。” docs.mongodb.com/manual/reference/operator/projection/elemMatch
  • 你是否在后端使用 PHP 运行查询($elemMatch 看起来像那样)?
  • 你为什么要拉 所有 cmets ?我想你会想要实现某种分页/限制,不是吗?无论您使用什么解决方案,一次拉出所有 cmets 的想法都不会很好地扩展。你能解释一下需要你拉取用户喜欢的所有 cmets 的用例吗?

标签: database mongodb parse-platform mongodb-query parse-server


【解决方案1】:

我建议您再次直接访问 MongoDB,除非您绝对必须这样做;毕竟,构建集合和关系的方式是 Parse 的一个实现细节,理论上将来可能会发生变化,从而破坏您的代码。

即使您想避免多个查询,我建议您这样做(根据您的平台,您甚至可以并行运行两个 Parse 查询):

  1. 第一个是Comment上的查询,用于获取您要显示的所有cmets;假设您有某种类型的 Post 可以为其编写 cmets,则查询将找到所有引用当前帖子的 cmets。
  2. 第二个查询又是针对Comment,但这次
    • 受限于在第一个查询中检索到的 cmets,例如:containedIn("objectID", arrayOfCommentIDs)
    • 并限制为在其likers 关系中具有当前用户的 cmets,例如:equalTo("likers", currentUser)

【讨论】:

  • 暂时接受,因为在 Parse Server 中直接访问 mongodb 确实非常复杂。但我仍然认为将来在 Parse Server 中实现 $elemMatch 或 $lookup 解决方案将是最好的:)
【解决方案2】:

好吧,连接集合并不是真正的 noSQL 思维方式;-) 我不知道ParseServer,所以下面只是基于纯MongoDB。

我要做的是,在评论文档中为每个喜欢评论的用户使用一个 ObjectId 数组。

示例文档布局

{ 
    "_id" : ObjectId(""), 
    "name" : "Comment X", 
    "liked" : [
        ObjectId(""), 
        ....
    ]
}

然后使用聚合来获取数据。我假设你有评论的 _id 并且你知道用户的 _id。

以下聚合返回带有点赞计数和布尔值的评论,表示用户喜欢评论。

db.Comment.aggregate(

    [
        {
            $match: {
            _id : ObjectId("your commentId")
            }
        },
        {
            $project: {
                _id : 1,
                name :1,
                number_of_likes : {$size : "$liked"},
                user_liked: {
                            $gt: [{
                                $size: {
                                    $filter: {
                                        input: "$liked",
                                        as: "like",
                                        cond: {
                                            $eq: ["$$like", ObjectId("your userId")]
                                        }
                                    }
                                }
                            }, 0]
                        },
            }
        },
    ]
);

返回

{ 
"_id" : ObjectId(""), 
"name" : "Comment X", 
"number_of_likes" : NumberInt(7), 
"user_liked" : true

}

希望这是你的追求。

【讨论】:

  • 谢谢豪迈斯特。正如我在问题中所写的那样,“您可能会说我可以在评论表中创建一个数组字段喜欢者......但这似乎不是一个好主意,因为可能会有成千上万的评论喜欢。” ...您认为将喜欢的人存储在数组中实际上是个好主意吗?每个 db 对象可能有一些大小限制,对吧?恐怕假设,如果用户给一个评论几千个赞,它就会坏掉。
  • @DavidRiha 对不起错过了。文档限制为 16MB!但是您可以在达到该限制之前将大量对象 ID 存储在一个数组中。当您担心文档大小超过 16MB 时,您可以查看一些解决方案。干杯!
  • @DavidRiha 您可以研究的一个潜在解决方案是使用“延续”文档。如果你有《MongoDB 权威指南》这本书,请查看关于非规范化的章节“Will Wheathon 效应”。如果您有任何问题,请告诉我!
猜你喜欢
  • 2015-03-01
  • 2014-02-08
  • 2012-02-28
  • 2021-01-31
  • 1970-01-01
  • 2014-02-09
  • 2020-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多