首页 > 解决方案 > 带有外域_id的mongodb $lookup

问题描述

我想使用 $lookup 获取结果,将本地字段作为 _id 的数组作为字符串。但它没有发生。我也尝试过使用 _id.str 但仍然没有结果。

db.posts.aggregate([

{
    $addFields: {
        TagCount: { $size: "$tags" }
    }
},
{
    $lookup:
    {
        from: "tags",
        localField: "tags",
        foreignField: "_id",
        as: "tagList"
    }
},
]));

Post Collection 的架构

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true,
    minlength: 10,
    set: v => v.replace(/\s\s+/gi, ' '),
    get: v => { console.log(v); return v.replace(/\s\s+/gi, ' '); }
  },
  content: {
    type: String,
    required: true
  },
  headerImage: {
    type: String
  },
  tags: [{
    type: mongoose.Schema.Types.ObjectId,
    required: true,
    validate: {
    validator: function (v) {
       return v.length > 0;
    }
  },
  message: 'There must be one tag',
  ref: 'tags'
 }],
  creationDate: { type: Date, default: Date.now }
 });

这是标签架构集合

 const tagSchema = new mongoose.Schema({
   name: {
    type: String,
    required: true,
    minlength: 3,
    set: value => value.replace(/\s\s+/gi, ' '),
    get: value => value.replace(/\s\s+/gi, ' ')
  },
  description: {
    type: String
  },
  creationDate: {
    type: Date,
    default: Date.now
 }  
 }, {
 collection: 'tags'
});

另外,我尝试了其他 StackOverflow 问题,但没有找到任何解决方案。

标签: mongodbmongodb-queryaggregation-frameworklookup

解决方案


ref: 'tags'在数组的架构定义中包含tagsmongoose 将值存储为 DBRef,而不是 ObjectID。

如果您打算使用该populate功能在客户端检索标记文档,这将非常有用。

聚合中的字段名称是$id$ref$db,它们在使用点分表示法时不是有效的字段名称,就像您在聚合管道中需要做的那样。

您可以将每个对象转换为一个数组,这将使它看起来像[ {"k":"$id", v:ObjectId("...")}, {"k":"$ref","v":"tags"}, {"k":"$db","v":"dbname"}]

然后过滤$id键,保留对应的值,并将该数组用作本地字段。

db.posts.aggregate([
  {$addFields: {
      TagCount: {$size: "$tags"},
      tag_ids: {
        $map: {
          input: "$tags",
          as: "dbref",
          in: {
            $reduce: {
              input: {$objectToArray: "$$dbref"},
              initialValue: [],
              in: {
                $cond: {
                  if: {$eq: ["$$this.k",{$literal: "$id"}]},
                  then: "$$this.v",
                  else: "$$value"
                }
              }
            }
          }
        }
      }
  }},
  {
    $lookup: {
      from: "tags",
      as: "tag_list",
      localField: "tag_ids",
      foreignField: "_id"
    }
  }
])

推荐阅读