简体   繁体   中英

How to convert string to ObjectId type and use in $lookup for mongodb?

I want to get the business information with businessId as a reference. However, I can't get the correct data because the previous developer did not use ObjectId type on the model. Now what I want to do is convert the businessId type to objectId withough altering the model, it would be easy if I do it but the old data will be affected, which is not good. Please see below for the model

const scanHistory = new Schema({
  businessId: { type: String },
  domains: [
    {
      domainId: { type: String },
      scanType: { type: String },
      status: { type: String },
      reportUrl: { type: String },
      scanStart: { type: Date, default: Date.now },
      scanFinish: { type: Date, default: Date.now }
    }
  ],
  scanStart: { type: Date, default: Date.now },
  scanStatus: { type: String },
  scanType: { type: String }
});

This is my aggregate query

    .collection("scanhistories")
    .aggregate([
      {
        $addFields: {
          businessObjId: {
            $convert: {
              input: "businessId",
              to: "objectId",
              onError: "Could not convert to type ObjectId."
            }
          }
        }
      },
      {
        $group: {
          _id: { $max: "$businessId" },
          businessObjId: { $max: "$businessId" },
          scanStatus: { $max: "$scanStatus" },
          scanStart: { $max: "$scanStart" },
          domains: { $max: "$domains" }
        }
      },

      {
        $lookup: {
          from: "businesses",
          as: "businessInfo",
          localField: "businessObjId",
          foreignField: "_id"
        }
      },
      {
        $project: {
          _id: 1,
          businessObjId: 1,
          primaryDomain: { $arrayElemAt: ["$businessInfo.primaryDomain", 0] },
          businessName: { $arrayElemAt: ["$businessInfo.businessName", 0] },
          frequency: { $arrayElemAt: ["$businessInfo.scanFrequency", 0] },
          scanStatus: 1,
          domains: 1
        }
      },
      {
        $match: {
          scanStatus: { $in: ["running", "undef"] },
          domains: { $exists: true }
        }
      }
    ])
    .toArray();

  for (let x = 0; x < history.length; x++) {
    console.log(history[x]);
  }

Now the output is like this which is not the one I expected.

{ _id: 5de09321bdb7cc07b7595de4,
  businessObjId: 5de09321bdb7cc07b7595de4,
  scanStatus: 'undef',
  domains:
   [ { _id: 5dfa626300007c243c1528b3,
       domainId: '5de09321bdb7cc07b7595de5',
       scanType: 'scheduled',
       status: 'running',
       reportUrl: '',
       scanStart: 2019-12-18T17:31:14.754Z,
       scanFinish: 2019-12-18T17:31:14.754Z } ] }

The expected result should have been with the lookup businessInfo that I wanted

{ _id: 5de09321bdb7cc07b7595de4,
  businessObjId: 5de09321bdb7cc07b7595de4,
  scanStatus: 'undef',
  domains:
   [ { _id: 5dfa626300007c243c1528b3,
       domainId: '5de09321bdb7cc07b7595de5',
       scanType: 'scheduled',
       status: 'running',
       reportUrl: '',
       scanStart: 2019-12-18T17:31:14.754Z,
       scanFinish: 2019-12-18T17:31:14.754Z } ],
       primaryDomain: "mydomainxxx.xy",
       businessName: "The biz",
       scanFrequency: "daily"

 }

Can you help me? I am really new to MongoDB and my background is PHP/SQL so all advises will be much appreciated. Thank you!

So I have found the solution for this. It was just a single mistake. :(

So on the aggregate code above where the group pipeline is. I made a mistake here.

Previous code above

{
  $group: {
    _id: { $max: "$businessId" },
    businessObjId: { $max: "$businessId" },
    scanStatus: { $max: "$scanStatus" },
    scanStart: { $max: "$scanStart" },
    domains: { $max: "$domains" }
   }
},

Correct one I change this part here:

businessObjId: { $first: "$businessObjId" }

{
  $group: {
     _id: { $max: "$businessId" },
     businessObjId: { $first: "$businessObjId" },
     scanStatus: { $max: "$scanStatus" },
     scanStart: { $max: "$scanStart" },
     domains: { $max: "$domains" }
  }
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM