MongoDB $lookup 管道匹配 _id 不起作用 [英] MongoDB $lookup pipeline match by _id not working

查看:46
本文介绍了MongoDB $lookup 管道匹配 _id 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在集合中执行 $lookup 并向我的文档添加一些数据.问题是,当我尝试通过 _id 匹配我的 $lookup 管道时,它返回一个空数组.这是我的代码:

i'm trying to do a $lookup in a collection and add some data to my documents. The problem is that when i try matching my $lookup pipeline by _id it returns an empty array. Here is my code:

Schedule.aggregate([{ // My Schedule schema
  $match: {
    store: req.query.store,
    "customer.id": req.query.user
  }
},
{
  $skip: +req.query.skip
}, {
  $limit: +req.query.limit
},
{
  $lookup: {
    from: Employee.collection.name, // "employee" schema,
    let: {
      id: "$employee.id" // employee _id from the "schedule" collection match above
    },
    pipeline: [{
        $match: {
          $expr: {
            "_id": "$$id" // here i try to match by _id
          }
        }
      },
      {
        $project: { // the only fields i need
          "_id": 1,
          "avatar": 1,
          "name": 1
        }
      }
    ],
    as: "employees" // employees is returned as []
  }
}
]).exec((err, resolve) => {
  if (err) console.log('error', err);
  res.json(resolve);
});

如果有帮助,这里是我在此聚合中使用的两个集合:

If it helps here's both my collections used in this aggregation:

计划架构:

const ScheduleSchema = new Schema({
  store: {
    type: String,
    required: true
  },
  customer: {
    id: {
      type: String
    },
    name: {
      type: String
    },
    avatar: String,
    phone: {
      type: String
    },
    email: { type: String },
    doc: {
      type: String
    },
  },
  employee: {
    id: {
      type: mongoose.Schema.Types.ObjectId,
      required: true
    },
    name: {
      type: String,
      required: true
    },
    avatar: String,
  },
  service: {
    id: {
      type: String
    },
    name: {
      type: String,
      required: true
    },
    filters: [String]
  },
  info: {
    channel: {
      type: String,
      required: true,
      default: 'app'
    },
    id: mongoose.Schema.Types.ObjectId,
    name: String
  },
  scheduleDate: {
    type: String,
    required: true
  },
  scheduleStart: {
    type: String,
    required: true
  },
  scheduleEnd: {
    type: String,
    required: true
  },
  value: {
    type: Number
  },
  comissionType: {
    type: String,
    default: '$'
  },
  comissionValue: {
    type: Number,
    default: 0
  },
  status: {
    type: Number,
    required: true
  },
  observation: String,
  paymentMethod: {
    type: Number,
    default: 0
  },
  paymentValue: String,
  paymentChange: String,
  color: String
}, {
    timestamps: {
      createdAt: 'created',
      updatedAt: 'updated'
    }
  });

员工架构:

const EmployeeSchema = new Schema({
  name: {
    type: String,
    required: true
  },
  a_to_z: String, // nome normalizado, só minusculas e sem espaços
  description: String,
  email: {
    type: String,
    required: true
  },
  avatar: String,
  phone: {
    type: String
  },
  storeOwner: {
    type: Boolean,
    required: true
  },
  permissions: [
    {
      route: String,
      hasPermission: Boolean
    }
  ],
  scheduleAutomatic: {
    type: Boolean,
    required: true,
    default: false
  },
  password: {
    passwordHash: String,
    salt: String
  },
  active: {
    type: Boolean,
    default: true
  },
  storeKey: {
    type: String,
    required: true
  },
  notification_token: String,
  notification_tokens: {
    type: [String],
    default: []
  },
  workingHours: [{
    weekDay: {
      type: Number,
    },
    doesWork: {
      type: Boolean,
    },
    startHour: String,
    endHour: String,
    lunchStart: String,
    lunchEnd: String
  }],
  config: {
    available_days: {
      type: Number,
      default: 365
    },
    in_advance_schedule: {
      type: Number,
      default: 0
    },
    in_advance_interval: {
      type: String,
      default: 'minute'
    }
  }
}, {
  timestamps: {
    createdAt: 'created',
    updatedAt: 'updated'
  } 
});

编辑

我想要达到的结果是:

EDIT

The result i'm trying to achieve is this:

employees 属性是我尝试使用 $lookup 获取的属性,它将与 employee 具有相同的数据> 属性,最终它会是一个对象数组,里面只有一个对象.

The employees property is the one i'm trying to use $lookup to get, it'll have the same data as the employee property, in the end it'll be and array of objects with just one object inside.

一些示例文档:

时间表:

color: "lavander",
created: "2018-07-31T18:50:53.423Z",
customer: {id: "5b60a67206e8a65f48a15f13", name: "Gabriel Barreto", phone: "11995274098", cpf: "40735255814"},
employee: {id: "5b2952c68424872fccece7f5", name: "Gabriel Barreto", avatar: null},
observation: "teste",
scheduleDate: "2018-08-01",
scheduleEnd: "2018-08-01 08:30",
scheduleStart: "2018-08-01 08:00",
service: {filters: Array(3), id: "5b606e8cc59e82354cc931e2", name: "Corte Masc"},
status: 1,
store: "5b16cceb56a44e2f6cd0324b",
updated: "2018-11-27T13:27:40.310Z",
value: 25,
__v: 0,
_id: "5b60af8de558661acc5d70b9"

员工:

a_to_z: "gabrielbarreto",
active: true,
avatar: "gabriel_barreto_h7qvcn.jpg",
config: {available_days: 180, in_advance_schedule: 10, in_advance_interval: "hour"},
created: "2018-06-19T19:00:22.315Z",
currency: "BRL",
description: "Novo perfil",
email: "gabriel.barreto@wabiz.com.br",
lang: "pt-BR",
name: "Gabriel Barreto",
notification_token: "2d768670-6011-4873-846d-39580b0d82d0",
notification_tokens: ["53049a82-53dc-4bc3-9646-7a4bee1f367b"],
password: null,
permissions: (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}],
phone: "11995274098",
scheduleAutomatic: false,
storeKey: "5b16cceb56a44e2f6cd0324b",
storeOwner: true,
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImdhYnJpZWwuYmFycmV0b0B3YWJpei5jb20uYnIiLCJpYXQiOjE1NTA2NzEwNDQsImV4cCI6MTU1MzI2MzA0NH0.0Odizd8pS4WPGSqm_2_XrTw1YE8NMOOXnHIrG-WVxGo",
updated: "2019-02-20T13:34:20.619Z",
workingHours: (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}],
__v: 0,
_id: "5b2952c68424872fccece7f5"

感谢您的时间

推荐答案

我在使用 $lookup 和 mongoose 尝试匹配 _id 时也遇到了麻烦,因为我的集合将引用存储为 String 而不是 ObjectId

I was in trouble too while using $lookup with mongoose to trying to match _id as my collection store the reference as a String and not an ObjectId

模型 A:{_id: ObjectId("xxx"), b_id: "eeeee"}

Model A: {_id: ObjectId("xxx"), b_id: "eeeee"}

模型 B:{_id: ObjectId("eeeee")}

Model B: {_id: ObjectId("eeeee")}

MyCollectionA.aggregate([
   {
      $lookup: {
        from: "collectionb",
        let: {id: "$b_id"},
        pipeline: [{$match: {$expr: {$eq: ["$_id", "$$id"]}}}],
        as: b
      }
])

在这个例子中,b 永远不会被填充,因为 $$id 不被认为是一个 ObjectId

In this example b is never filled as $$id is not considered as an ObjectId

只需添加一个项目来转换 objectId 中的 $$id 及其工作

Just add a project to transform $$id in an objectId and its working

MyCollectionA.aggregate([
   {
      $lookup: {
        from: "collectionb",
        let: {id: "$b_id"},
        pipeline: [
           {$project: {_id: 1, bid: {"$toObjectId": "$$id"}}},
           {$match: {$expr: {$eq: ["$_id", "$bid"]}}}
        ],
        as: b
      }
])

或者使用foreignField、localField:

Or with foreignField, localField:

MyCollectionA.aggregate([
   {
      $project:{
        _id: 1,
        b_id: {"$toObjectId": "$b_id"}
      }
   },
   {
      $lookup: {
        from: "collectionb",
        localField: "b_id",
        foreignField: "_id",
        as: b
      }
])

这篇关于MongoDB $lookup 管道匹配 _id 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆