1

模型

现在我有两个 PyMODM 模型:

class PlaylistTrack(MongoModel):
    post = fields.ReferenceField(Post, primary_key=True)
    playlist_position = fields.IntegerField() # Uses zero-indexing
class Post(MongoModel):
    reddit_post_id = fields.CharField(required=True, primary_key=True)
    subreddit = fields.CharField()
    exists_in_playlist = fields.BooleanField()
    #
    # ... some more irrelevant fields
    #

如您所见,PlaylistTrack模型包含对模型的引用 id Post

问题

在我的代码中,我想获取与某些 Post 字段以及 PlaylistTrack 字段匹配的所有 PlaylistTrack,如下所示:

# This is psuedocode, not actually valid PyMODM syntax
tracks = PlaylistTrack.objects.raw(
   {"post.subreddit": subreddit_name,
    "playlist_position": {"$gt": pos_in_spotify, "$lte": new_pos}}
)

PyMODM 不允许我这样做,因为 post 不是嵌入式文档,但它是另一个帖子的引用字段。在研究文档后,我发现 mongodbaggregate()管道与$lookup操作符相结合会做一个左外连接,让我可以做这样的事情:

        playlisttracks = PlaylistTrack.objects.all().aggregate(
                {
                    "$lookup": {
                        "from": "post",
                        "localField": "_id",
                        "foreignField": "_id",
                        "as": "playlisttrack_post"
                    }
                },
                {
                    "$match": {
                        "playlisttrack_post.subreddit": self.subreddit_name,
                        "playlisttrack_post.exists_in_playlist": True
                    }
                },
                {
                    "$sort": {"playlist_position": pymongo.ASCENDING}
                })

问题在于它返回的是 PyMongo CommandCursor 类型,而不是 PyMODM QuerySet 类型。这意味着我不能使用 QuerySet 类方法(与 PyMODM 模型一起使用更自然),而是必须将所有内容都转换为 PyMongo,这有点违背了使用 PyMODM 的目的和不自然的感觉。

我的解决方法

因此,相反,我将其作为一种 hacky 解决方法

posts = Post.objects.raw({"$and": 
    [{"subreddit": self.subreddit_name},
        {"exists_in_playlist": True}]})

post_ids = [p.reddit_post_id for p in posts]

# Get all tracks in playlist in order
playlisttracks = PlaylistTrack.objects \
        .raw({"_id": {"$in": post_ids}}) \
        .order_by([("playlist_position", pymongo.ASCENDING)]

我没有与 进行连接$lookup,而是找到我想要的 Post 并将其用作查询的一部分。

这确保返回的对象是 PyMODM QuerySet 对象。

我的问题

有没有更好的方法来使用本机 PyMODM 语法来解决这个问题?我是否误解了如何使用 PyMongo / PyMODM 的用途?

我知道在 NoSQL 中使用连接有点棘手,但我仍然觉得肯定有比这更好的方法。

4

0 回答 0