0

I have the authors and books test collections which have a many-to-many relationship between them.

> db.books.find()
[
  {
    _id: ObjectId("60a676f24312c6d8ea7bd6ec"),
    title: '300 years of peanut juggling: A longitudinal analysis.',
    inPrint: true,
    authors: [ '60a673c44312c6d8ea7bd6e9', '60a673c44312c6d8ea7bd6ea' ]
  },
  {
    _id: ObjectId("60a676f24312c6d8ea7bd6ed"),
    title: "Mystery Overflow: murder and chaos on the Web's biggest developer Q & A platform.",
    inPrint: true,
    authors: [ '60a673c44312c6d8ea7bd6eb' ],
    edition: 2
  }
]
> db.authors.find()
[
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6e9"),
    name: 'Jason Filippou',
    age: 33,
    nationalities: [ 'GRC, CND' ],
    books: [ '60a676f24312c6d8ea7bd6ec' ]
  },
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6ea"),
    name: 'Mary Chou',
    age: 39,
    nationalities: [ 'USA' ],
    books: [ '60a676f24312c6d8ea7bd6ec' ]
  },
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6eb"),
    name: 'Max Schwarz',
    age: 42,
    job: 'pilot',
    books: [ '60a676f24312c6d8ea7bd6ed' ]
  }
]

I implement the relationship externally, as can be seen by the authors and books fields. However, I have made the mistake of having the arrays of references be raw strings, instead of ObjectId types. This means that my joins as required by, e.g, $lookup()) fail.

I tried to mass update all the strings to make them ObjectIds using the command:

db.books.find({}).forEach(book => book.authors.forEach(id => ObjectId(id)))

While the command worked, the original data did not change:

> db.books.find({}).forEach(book => book.authors.forEach(id => ObjectId(id)))

> db.books.find()
[
  {
    _id: ObjectId("60a676f24312c6d8ea7bd6ec"),
    title: '300 years of peanut juggling: A longitudinal analysis.',
    inPrint: true,
    authors: [ '60a673c44312c6d8ea7bd6e9', '60a673c44312c6d8ea7bd6ea' ]
  },
  {
    _id: ObjectId("60a676f24312c6d8ea7bd6ed"),
    title: "Mystery Overflow: murder and chaos on the Web's biggest developer Q & A platform.",
    inPrint: true,
    authors: [ '60a673c44312c6d8ea7bd6eb' ],
    edition: 2
  }
]
> db.authors.find()
[
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6e9"),
    name: 'Jason Filippou',
    age: 33,
    nationalities: [ 'GRC, CND' ],
    books: [ '60a676f24312c6d8ea7bd6ec' ]
  },
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6ea"),
    name: 'Mary Chou',
    age: 39,
    nationalities: [ 'USA' ],
    books: [ '60a676f24312c6d8ea7bd6ec' ]
  },
  {
    _id: ObjectId("60a673c44312c6d8ea7bd6eb"),
    name: 'Max Schwarz',
    age: 42,
    job: 'pilot',
    books: [ '60a676f24312c6d8ea7bd6ed' ]
  }
]

What is my mistake here?

Jason
  • 2,495
  • 4
  • 26
  • 37

1 Answers1

0

If you decide to update all books string to ObjectId, u can use update-documents-with-aggregation-pipeline

db.authors.updateMany({},[
  {
    "$addFields": {
      "books": {
        "$map": {
          "input": "$books",
          "in": {
            "$toObjectId": "$$this"
          }
        }
      }
    }
  }
])
varman
  • 8,704
  • 5
  • 19
  • 53