Poor choice of document model in my opinion because the _id
can be “hacked” like this:
db.coll.insertMany([
{_id: {branchNumber: "London123", bald: 100}},
{_id: {bald: 100, branchNumber: "London123"}}
])
{
acknowledged: true,
insertedIds: {
'0': { branchNumber: 'London123', bald: 100 },
'1': { bald: 100, branchNumber: 'London123' }
}
}
So as you can see, I can totally insert these 2 documents in my collection and they have the “same” _id
but it’s technically different (because of the order) so I can do it but I wouldn’t recommend it at all as it’s technically possible to insert a “duplicated” entry in my database from the business point of view.
A better implementation would be to use a standard ObjectId for the _id
field and 2 normal fields for branchNumber
and bald
with a compound unique index on them to ensure uniqueness.
test [direct: primary] test> db.coll.deleteMany({})
{ acknowledged: true, deletedCount: 2 }
test [direct: primary] test> db.coll.createIndex({branchNumber: 1, bald: 1}, {unique: 1})
branchNumber_1_bald_1
test [direct: primary] test> db.coll.insertMany([{branchNumber: "London123", bald: 100},{bald: 100, branchNumber: "London123"}])
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: test.coll index: branchNumber_1_bald_1 dup key: { branchNumber: "London123", bald: 100 }
Result: BulkWriteResult {
result: {
ok: 1,
writeErrors: [
WriteError {
err: {
index: 1,
code: 11000,
errmsg: 'E11000 duplicate key error collection: test.coll index: branchNumber_1_bald_1 dup key: { branchNumber: "London123", bald: 100 }',
op: {
bald: 100,
branchNumber: 'London123',
_id: ObjectId("6137714d2b36246158d0f720")
}
}
}
],
writeConcernErrors: [],
insertedIds: [
{ index: 0, _id: ObjectId("6137714d2b36246158d0f71f") },
{ index: 1, _id: ObjectId("6137714d2b36246158d0f720") }
],
nInserted: 1,
nUpserted: 0,
nMatched: 0,
nModified: 0,
nRemoved: 0,
upserted: [],
opTime: { ts: Timestamp({ t: 1631023437, i: 3 }), t: Long("1") }
}
}
test [direct: primary] test> db.coll.find()
[
{
_id: ObjectId("6137714d2b36246158d0f71f"),
branchNumber: 'London123',
bald: 100
}
]
As you can see in the above example, this implementation isn’t order-dependant and it’s bug-proof from the business point of view.
Now. To remove these documents from your current collection in it’s current state, I would send a query that isn’t order dependant in order to remove all the possible versions of this document: {_id: {a:1, b:1}}
and {_id: {b:1, a:1}}
.
The trick is to use the dot notation:
test [direct: primary] test> db.coll.insertMany([{_id:{branchNumber: "London123", bald: 100}},{_id: {bald: 100, branchNumber: "London123"}}])
{
acknowledged: true,
insertedIds: {
'0': { branchNumber: 'London123', bald: 100 },
'1': { bald: 100, branchNumber: 'London123' }
}
}
test [direct: primary] test> db.coll.find()
[
{ _id: { branchNumber: 'London123', bald: 100 } },
{ _id: { bald: 100, branchNumber: 'London123' } }
]
test [direct: primary] test> db.coll.deleteMany({"_id.branchNumber": "London123", "_id.bald": 100})
{ acknowledged: true, deletedCount: 2 }
Here is some more doc using the Java Driver (change the language on the right).
In the end, your delete query should look like this:
(and(eq("_id.branchNumber": "London123"), eq("_id.bald", 100)))
I hope this helps.
Cheers,
Maxime.