有没有比这更好的方法来使用PyMODM QuerySet类进行$lookup(即连接)?

2024-10-02 00:43:33 发布

您现在位置:Python中文网/ 问答频道 /正文

模型

现在我有两个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模型包含对Post模型的引用id

问题

在我的代码中,我希望获得与某个Post字段和PlayTrack字段匹配的所有PlayTrack,如下所示:

# 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的目的和不自然

我的变通方法

因此,相反,我做这件事是作为一个黑客的解决办法

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进行连接,而是找到我想要的帖子,并将其作为查询的一部分

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

我的问题

有没有更好的方法使用原生PyMODM语法来实现这一点?我是否误解了如何使用PyMongo/PyMODM,因为它们是预期使用的

我知道在NoSQL中使用连接有点棘手,但我还是觉得一定有比这更好的方法


Tags: in模型idtruefieldsrawobjectsexists

热门问题