使用PHP进行MongoDB $lookup时,将_id作为foreignField如何操作?

3

我已经为这个问题苦思冥想太久了...

我有两个MongoDB集合:"chatroom"和"users"。 "chatroom"集合具有指向"users"集合中特定单个用户的"user_id"键。

我正在尝试使用$lookup聚合查询获取与用户相关的聊天室,目前我的查询语句如下:

$this->mongo->chatroom->aggregate(
    array('$lookup' => array(
        'from' => 'users',
        'localField' => 'user_id',
        'foreignField' => '_id',
        'as' => 'user'
    ))
);

然而,这会在集合中返回一个空的"user"字段。奇怪的是,如果我尝试用自定义的"uid"替换"_id",并将其设置为_id.$id的值,它就能按预期工作:

$this->mongo->chatroom->aggregate(
    array('$lookup' => array(
        'from' => 'users',
        'localField' => 'user_id',
        'foreignField' => 'uid', // uid = _id.$id
        'as' => 'user'
    ))
);

我发现问题是"_id"是一个ObjectId类型,而"user_id"是一个字符串类型。但我不知道如何优雅地处理这个问题...
1个回答

3
为了回答我的问题,我通过将“user_id”作为“MongoId”类的实例而不是普通字符串来解决这个问题。基本上,我将“user_id”存储为:
$mongoObject["user_id"] = new MongoId($this->user_id);

另一种解决方案可能是使用“uid”字段来装饰对象,其值等于“_id.$id”。


2
实际上这根本不是“绕过问题”,而是“纠正”问题。就像发出任何查询一样,数据必须具有相同的“类型”以匹配。因此,"localField""foreignField"必须具有相同的 BSON 类型,否则后续的“查询”将失败。就像如果您尝试使用提供的字符串而不是重新转换的 _id 查询您的 users 集合,那么该查询将不返回任何结果。没有区别,并且是按设计方式实现的。 - Blakes Seven
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Petr Dvořák
1
你不能在聚合中“重新转换”类型(虽然有一些有趣的例外,但这是一般规则),至少对于ObjectId而言是如此。正确的做法是将两种类型都更改为相同的类型,以确保它们确实“匹配”。另外,始终使用mongo shell来检查数据。它可能缺乏“花哨”的功能,但它是“保证”向您显示正确类型的唯一产品。这是一个官方产品,所以应该期望如此。接受你自己的答案。这是正确的方法。 - Blakes Seven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接