Update with upsert and $inc modifier breaks find()

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Done
    • Priority: Major - P3
    • None
    • Affects Version/s: 1.6.5, 1.8.0
    • Component/s: None
    • None
    • 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.
    • ALL
    • None
    • 3
    • None
    • None
    • None
    • None
    • None
    • None

      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.

            Assignee:
            Unassigned
            Reporter:
            Duo Zheng
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: