【问题、AI解答】mongodb中使用$lookup进行连表查询使用_id作为localField出现查询结果字段为空的情况

描述:

db.acticles.aggregate([
{
	$lookup:
	{
	from:"acticlesMaptags",
	localField:"_id",
	foreignField:"acticleid",
	as:"tagid"
	}
}
])

acticlesMaptags集合中的acticleid字段存在与acticles集合中的_id相匹配的数据,但是查询出来的tagid却为空。
在这里插入图片描述

下面是acticles集合与acticlesMaptags集合:

{
  "RECORDS": [
    {
      "_id": "6436ba99e0180000d2007562",
      "title": "这是标题",
      "text": "这是内容",
      "descripe": "接上期,MongoDB 的事务操作已经操作了,但细节和参数并没有弄清楚,通过mongodb 的事务操作主要分为以下几个部分1 Session.startTransaction2 ...",
      "time": "1681308703868"
    },
    {
      "_id": "6436ba9de0180000d2007563",
      "title": "这是标题",
      "text": "这是内容",
      "descripe": "事务是数据库中处理的逻辑单元,包括一个或多个数据库操作,既可以是读操作,也可以是写...要使用事务,你所部署的 MongoDB 必须是 MongoDB 4.2 或更高版本,MongoDB 的驱动程序必须更新为 MongoDB 4.2 或更高版本。...",
      "time": "1681308703868"
    },
    {
      "_id": "6436c0dce0180000d200756c",
      "title": "测试标题",
      "text": "这是内容",
      "descripe": "的哦奥球",
      "time": "1681308703868"
    }
  ]
}
{
  "RECORDS": [
    {
      "_id": "6436bfb9e0180000d200756a",
      "acticleid": "6436ba99e0180000d2007562",
      "tagid": "6436be71e0180000d2007565"
    },
    {
      "_id": "6436bff2e0180000d200756b",
      "acticleid": "6436ba9de0180000d2007563",
      "tagid": "6436bebae0180000d2007569"
    },
    {
      "_id": "6436c316e0180000d200756d",
      "acticleid": "6436c0dce0180000d200756c",
      "tagid": "6436be97e0180000d2007567"
    },
    {
      "_id": "6436c38ce0180000d200756e",
      "acticleid": "6436c0dce0180000d200756c",
      "tagid": "6436be97e0180000d2007567"
    },
    {
      "_id": "6438b4b0fe580000ec007ff2",
      "acticleid": "6436ba9de0180000d2007563",
      "tagid": "6436be97e0180000d2007567"
    }
  ]
}

ai的回答:

根据您提供的文档,从逻辑上看 $lookup 查询语句是正确的,但是结果为空可能有以下几个可能性:

acticlesMaptags 集合中的 acticleid 字段中的值与 acticles 集合中的 _id 字段值不完全匹配。请注意确保两个集合之间使用相同类型的字段进行关联(例如,都使用 ObjectID 类型)。
如果您在执行 $lookup 查询时未指定相关的查询条件,则将从 acticlesMaptags 集合中检索所有与 acticles 集合中的文档匹配的记录,这可能会返回大量数据并导致查询超时或者无法查询出结果。 基于您的数据,这种情况似乎不太可能发生。
另外一个可能性是访问权限问题。请确保您有足够的权限访问 acticlesMaptags 集合。
我们建议你通过对 acticlesMaptags 进行简单的聚合查询来验证集合中是否存在与 acticles 集合中的 _id 字段匹配的文档。例如,可以执行以下查询:

db.acticlesMaptags.aggregate([
  {
    $match: {
      acticleid: {
        $in: db.acticles.distinct("_id")
      }
    },
  }
])

此查询将返回 acticlesMaptags 集合中与 acticles 集合中的 _id 字段匹配的文档。如果没有返回结果,则可能存在相关性或访问权限问题,您需要进一步进行排查。

解决

根据ai的回答我可以判断是类型不相同出现的问题,于是我还问了下ai的解决方案:
在MongoDB中,使用lookup可以实现表连接的操作。
lookup可以实现表连接的操作。lookup运算符可以将文档从一个集合连接到另一个集合,并将结果作为新的嵌入式文档数组返回。

如果要连接两个不同类型的字段(例如ObjectId和字符串),可以使用以下方式:

假设有两个集合:orders和customers。orders集合中包含一个名为customerId的ObjectId字段,而customers集合中包含一个名为_id的字符串字段。要在orders集合中查找所有订单,以及与之相关联的客户信息,请执行以下步骤:

db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customerId",
      foreignField: "_id",
      as: "customer_info"
    }
  }
])

上述代码将在orders集合中查找所有订单,并将customer_info字段添加到每个订单文档中。该字段是一个由查询customers集合得到的包含客户信息的数组。其中localField指定了在orders集合中用于匹配的字段,而foreignField指定了在customers集合中用于匹配的字段。

需要注意的一点是,如果要连接的两个字段类型不同,则需要将localField字段的值写成一个对象,其中包含了类似 $toString 和 $toObjectId 等转换方法。例如,如果orders集合的customerId字段是一个字符串而非ObjectId,则可采用如下方式进行转换:

db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: { $toObjectId: "$customerId" },
      foreignField: "_id",
      as: "customer_info"
    }
  }
])

上述代码将使用$toObjectId运算符将customerId字段从字符串转换为ObjectId。然后,它将在customers集合中查找与之匹配的文档,并将结果包含在customer_info字段中。

最终我的解决方案

添加一个转换为string类型的_id字段。

db.acticles.aggregate([
  {
    $addFields: {
      acticleid: { $toString: "$_id" }
    }
  },
{
	$lookup:
	{
		from:"acticlesMaptags",
		localField:"acticleid",
		foreignField:"acticleid",
		as:"tagid"
	}
}
])

成功!!!
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值