[SERVER-16783] Indexes not updated when types change but values compare equally Created: 08/Jan/15  Updated: 06/Dec/22  Resolved: 12/Dec/17

Status: Closed
Project: Core Server
Component/s: Index Maintenance, Write Ops
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Mathias Stearn Assignee: Backlog - Storage Execution Team
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-16801 update considers a change in numerica... Closed
Assigned Teams:
Storage Execution
Operating System: ALL
Participants:

 Description   

The AccessMethod code above the indexes groups values into added, removed, and unchanged based on value comparisons. Since this doesn't consider types, all values where only the type changed are considered "unchanged" and the index is not notified of the change.

> db.foo.insert({_id:1, a:1})
WriteResult({ "nInserted" : 1 })
> db.foo.ensureIndex({a:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.foo.find({a:1}, {a:1, _id:0})
{ "a" : 1 }
> db.foo.save({_id:1, a: NumberLong(1)})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.find({a:1}, {a:1, _id:0})
{ "a" : 1 }
> db.foo.find({a:1}, {a:1, _id:0}).hint({$natural: 1})
{ "a" : NumberLong(1) }



 Comments   
Comment by Asya Kamsky [ 01/Sep/16 ]

This works correctly on 3.3.12:

(3.3.12) > db.foo.insert({_id:1, a:1})
WriteResult({ "nInserted" : 1 })
(3.3.12) > db.foo.ensureIndex({a:1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}
(3.3.12) > db.foo.find({a:1}, {a:1, _id:0})
{ "a" : 1 }
(3.3.12) > db.foo.save({_id:1, a: NumberLong(1)})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
(3.3.12) > db.foo.find({a:1}, {a:1, _id:0})
{ "a" : NumberLong(1) }
(3.3.12) > db.foo.find({a:1}, {a:1, _id:0}).hint({$natural: 1})
{ "a" : NumberLong(1) }

Fixed as part of SERVER-16801 work?

In distinct example only one value is returned in middle case (also correctly).

Recommend fixing this as fixed or duplicate of fixed.

Comment by Mathias Stearn [ 08/Jan/15 ]

Actually, this may be unsolvable. Using distinct since we don't do normal covered queries with multikey indexes.

> db.foo.drop()
true
> db.foo.ensureIndex({a:1})
{
        "createdCollectionAutomatically" : true,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.foo.save({_id:1, a: [1]})
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 1 })
> db.foo.distinct('a')
[ 1 ]
> db.foo.save({_id:1, a: [1, NumberLong(1)]})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.distinct('a')
[ 1 ]
> db.foo.save({_id:1, a: [NumberLong(1)]})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.distinct('a')
[ 1 ]
> db.foo.dropIndex({a:1})
{ "nIndexesWas" : 2, "ok" : 1 }
> db.foo.distinct('a')
[ NumberLong(1) ]

I really don't think we want two entries in the middle case.

Comment by J Rassi [ 08/Jan/15 ]

Reproduces on 2.2/2.4/2.6/master.

Generated at Thu Feb 08 03:42:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.