[SERVER-2910] Update with upsert and $inc modifier breaks find() Created: 06/Apr/11  Updated: 12/Jul/16  Resolved: 18/Sep/12

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: 1.6.5, 1.8.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Duo Zheng Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Linux version 2.6.31-22-server (buildd@allspice) (gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) ) #69-Ubuntu SMP Wed Nov 24 09:25:59 UTC 2010

Test ran on 1.6.5 and reproduced on 1.8.0.


Operating System: ALL
Participants:

 Description   

There is a strange bug when using update() with a upset and a large $inc modifier. This bug is best explained with a reproducible example.

1.
use testbug;

2.
db.metrics.ensureIndex(

{name: 1,period: 1, start_date: 1,aggregates: 1}

);

3.
db.metrics.update(

{'name': 'tab_content.tabviews', 'period': 'day', 'end_date': '2010-11-02 23:59:59', 'start_date': '2010-11-02 00:00:00'}

,
{'$inc': {'aggregates.2204': 1, 'aggregates.241': 3, 'aggregates.2061': 1, 'aggregates.549': 2, 'aggregates.1634': 1, 'aggregates.1242': 1, 'aggregates.1269': 1, 'aggregates.75': 1, 'aggregates.2023': 79, 'aggregates.2245': 1, 'aggregates.987': 13, 'total': 200, 'aggregates.497': 1, 'aggregates.553': 1, 'aggregates.715': 1, 'aggregates.304': 9, 'aggregates.1842': 1, 'aggregates.1840': 1, 'aggregates.151': 2, 'aggregates.297': 2, 'aggregates.499': 1, 'aggregates.2238': 7, 'aggregates.932': 1, 'aggregates.1513': 4, 'aggregates.1270': 1, 'aggregates.2074': 11, 'aggregates.1579': 11, 'aggregates.2230': 3, 'aggregates.1398': 5, 'aggregates.285': 1, 'aggregates.2366': 1, 'aggregates.2033': 1, 'aggregates.1498': 3, 'aggregates.1355': 1, 'aggregates.628': 2, 'aggregates.233': 1, 'aggregates.166': 2, 'aggregates.1290': 5, 'aggregates.1796': 7, 'aggregates.2003': 2, 'aggregates.925': 2, 'aggregates.101': 1, 'aggregates.1793': 5}},
true);

4.
db.metrics.find(

{start_date: '2010-11-02 00:00:00', name: 'tab_content.tabviews', period: 'day'}

).pretty();
// Document in Step 3 is returned as expected.

5.
db.metrics.update(

{'name': 'tab_content.tabviews', 'period': 'day', 'end_date': '2010-11-02 23:59:59', 'start_date': '2010-11-02 00:00:00'}

,
{'$inc': {'aggregates.2238': 15, 'aggregates.2108': 1, 'aggregates.2204': 2, 'aggregates.1634': 1, 'aggregates.297': 3, 'aggregates.1244': 1, 'aggregates.1111': 1, 'aggregates.2023': 65, 'aggregates.2245': 1, 'aggregates.987': 5, 'total': 200, 'aggregates.264': 2, 'aggregates.1868': 1, 'aggregates.249': 2, 'aggregates.910': 2, 'aggregates.166': 1, 'aggregates.304': 4, 'aggregates.303': 3, 'aggregates.497': 3, 'aggregates.73': 1, 'aggregates.1750': 1, 'aggregates.499': 1, 'aggregates.498': 1, 'aggregates.1781': 1, 'aggregates.1826': 1, 'aggregates.2074': 8, 'aggregates.1579': 18, 'aggregates.1398': 11, 'aggregates.1513': 6, 'aggregates.646': 3, 'aggregates.1760': 1, 'aggregates.75': 2, 'aggregates.1355': 3, 'aggregates.233': 1, 'aggregates.1292': 1, 'aggregates.1290': 5, 'aggregates.1855': 1, 'aggregates.961': 2, 'aggregates.724': 2, 'aggregates.1796': 4, 'aggregates.647': 1, 'aggregates.1793': 11, 'aggregates.129': 1}},
true);

6.
db.metrics.find(

{start_date: '2010-11-02 00:00:00', name: 'tab_content.tabviews', period: 'day'}

).pretty();
// After the second update in Step 5, nothing is returned for this query now.

7.
db.metrics.find();
// This will return the document we want.

8.
db.metrics.update(

{'name': 'tab_content.tabviews', 'period': 'day', 'end_date': '2010-11-02 23:59:59', 'start_date': '2010-11-02 00:00:00'}

,
{'$inc': {'aggregates.2204': 3, 'aggregates.2106': 1, 'aggregates.1637': 1, 'aggregates.71': 2, 'aggregates.1244': 1, 'aggregates.166': 2, 'aggregates.1187': 1, 'aggregates.2023': 91, 'aggregates.987': 6, 'total': 200, 'aggregates.963': 2, 'aggregates.266': 1, 'aggregates.553': 2, 'aggregates.715': 1, 'aggregates.304': 4, 'aggregates.497': 3, 'aggregates.1840': 2, 'aggregates.2238': 11, 'aggregates.1780': 1, 'aggregates.2105': 2, 'aggregates.2074': 11, 'aggregates.1579': 13, 'aggregates.2230': 1, 'aggregates.1398': 4, 'aggregates.1513': 2, 'aggregates.1355': 1, 'aggregates.549': 2, 'aggregates.1292': 1, 'aggregates.1290': 5, 'aggregates.1855': 1, 'aggregates.214': 1, 'aggregates.1796': 6, 'aggregates.1793': 13, 'aggregates.1956': 2}},
true);

9.
db.metrics.find(

{start_date: '2010-11-02 00:00:00', name: 'tab_content.tabviews', period: 'day'}

).pretty();
// Only the document in Step 8 was returned.

10.
db.metrics.find();
// Finds 2 separate documents.

Note

  • After step 6, running a db.metrics.find( {start_date: '2010-11-02 00:00:00', name: 'tab_content.tabviews', period: 'day'}

    ).explain();
    {
    "cursor" : "BtreeCursor start_date_1_name_1_period_1_aggregates_1",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
    "indexBounds" :

    Unknown macro: { "start_date" }

    }

  • When using a $inc modifier with only a single property increment, the bug does not exist.
  • If the index is modified to be {start_date: 1, name: 1, period: 1}

    then the bug no longer exists as we can tell. Our current fix is to use this index as we have no current direct use for indexing the "aggregates" property. This bug though to the best of our knowledge does not seem to be intended and by design.



 Comments   
Comment by Eliot Horowitz (Inactive) [ 18/Sep/12 ]

This was fixed in 2.0.0

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