[SERVER-34856] equality operators with object values delete all documents where field is a document or array of documents Created: 04/May/18  Updated: 27/Oct/23  Resolved: 07/May/18

Status: Closed
Project: Core Server
Component/s: Querying, Sharding
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Esha Maharishi (Inactive) Assignee: Asya Kamsky
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Steps To Reproduce:

    var mongod = MongoRunner.runMongod();
    let db = mongod.getDB("test");
    let coll = db.getCollection("coll");
 
    assert.commandWorked(coll.insert({ a: { "y": 1 }}));
    assert.commandWorked(coll.insert({ a: { "y": 2 }}));
    assert.commandWorked(coll.insert({ a: { "x": 1 }}));
    assert.commandWorked(coll.insert({ a: { "x": 2 }}));
    assert.commandWorked(coll.insert({ a : "string" }));
    assert.commandWorked(coll.insert({ a : "123" }));
    assert.commandWorked(coll.insert({ a: [ "string in array" ] }));
    assert.commandWorked(coll.insert({ a: [ { "foo": "string in object in array"} ] }));
    print("coll after inserts: " + tojson(coll.find().toArray()));
    assert.eq(8, coll.count());
 
    assert.commandWorked(db.runCommand({ delete: "coll", ordered: true, deletes: [ { q: { a: { "$gte": { "x.x": 100 }}}, limit: 0 }] }));
    print("coll after remove " + tojson(coll.find().toArray()));
    assert.eq(8, coll.count()); // expect fail 

Participants:

 Description   

Using $gte or $lt with an object value

deletes: [ { q: { a: { "$gte": { "x.x": 100 }}}, limit: 0 }]

seems to delete all documents where "a" is a document or array of documents (see repro script).

Is this expected behavior?



 Comments   
Comment by Esha Maharishi (Inactive) [ 07/May/18 ]

asya explained offline that, if you sort these documents, they are first sorted by type (number, string, object), then within each type, by field name.

Closing as Works as Designed.

Comment by Esha Maharishi (Inactive) [ 05/May/18 ]

asya, ah, you're right, I was fiddling around with the query and probably didn't notice that this query only deletes 3 of the documents because of the way I wrote the repro.

I guess comparing objects is confusing - for example, why does

{ a: [ { "foo": "string in object in array"} ] }

get deleted? (Why is {"x": 1} < {"x.x": 100} <= {"foo": "string"}?)

Comment by Kaloian Manassiev [ 04/May/18 ]

Just for my own information - what is the difference then between $gte/$lte and $min/$max? I thought $gte/$lte do not accept whole BSON objects.

Comment by Asya Kamsky [ 04/May/18 ]

I ran that code - I didn't get that it deleted every document, just 3 out of the 8 there.

After delete:

db.coll.find()
{ "_id" : ObjectId("5aeccef173f01ec74e03d7f6"), "a" : { "x" : 1 } }
{ "_id" : ObjectId("5aeccef173f01ec74e03d7f7"), "a" : { "x" : 2 } }
{ "_id" : ObjectId("5aeccef173f01ec74e03d7f8"), "a" : "string" }
{ "_id" : ObjectId("5aeccef173f01ec74e03d7f9"), "a" : "123" }
{ "_id" : ObjectId("5aeccef173f01ec74e03d7fa"), "a" : [ "string in array" ] } 

Comment by Asya Kamsky [ 04/May/18 ]

This is correct since the query a:{$gte:ANY}  means any document where a is greater than or equal to ANY or a is an array that has an element that's >= ANY.

 

Generated at Thu Feb 08 04:38:04 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.