Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-100299

sort-skip-limit may return more documents than limit specifies

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 8.0.4
    • Component/s: None
    • Query Optimization
    • ALL
    • Hide
      const coll = db.coll;
      assert(coll.drop());
      assert.commandWorked(db.createCollection(coll.getName(), {
          timeseries: {timeField: 't', metaField: 'm'},
      }));
      
      assert.commandWorked(coll.insert([
          {
              "_id": 1,
              "t": new Date(1),
              "m": 1,
          },
          {
              "_id": 2,
              "t": new Date(2),
              "m": 2,
          },
          {
              "_id": 3,
              "t": new Date(3),
              "m": 3,
          },
          {
              "_id": 4,
              "t": new Date(4),
              "m": 4,
          }
      ]))
      
      
      const query = [
          {
              "$match": {
                  "$nor": [
                      {"t": {"$in": []}},
                  ]
              }
          },
          {"$sort": {"m": 1}},
          {"$skip": 1},
          {"$limit": 1}
      ];
      
      jsTestLog(coll.aggregate(query).toArray())
      // outputs 2 documents
      jsTestLog(coll.explain().aggregate(query))
      
      Show
      const coll = db.coll; assert (coll.drop()); assert .commandWorked(db.createCollection(coll.getName(), { timeseries: {timeField: 't' , metaField: 'm' }, })); assert .commandWorked(coll.insert([ { "_id" : 1, "t" : new Date(1), "m" : 1, }, { "_id" : 2, "t" : new Date(2), "m" : 2, }, { "_id" : 3, "t" : new Date(3), "m" : 3, }, { "_id" : 4, "t" : new Date(4), "m" : 4, } ])) const query = [ { "$match" : { "$nor" : [ { "t" : { "$in" : []}}, ] } }, { "$sort" : { "m" : 1}}, { "$skip" : 1}, { "$limit" : 1} ]; jsTestLog(coll.aggregate(query).toArray()) // outputs 2 documents jsTestLog(coll.explain().aggregate(query))

      In the repro provided, we have a query that ends with {$limit: 1}, but the query outputs 2 documents.

      The $match at the beginning of the pipeline is always true, but without it I couldn't repro the issue (for now). I think there's some more realistic $match that would also show the problem.

      Also based on the explain, I don't think a time-series collection is required. The "command" field shows we received a "skip 1, limit: 1", but then at the end of the optimized pipeline, there's a "skip 1, limit 2". I'm not aware of any specific skip/limit logic for time-series collections, so I've assigned this to QO.

            Assignee:
            sopho.kevlishvili@mongodb.com Sopho Kevlishvili
            Reporter:
            matt.boros@mongodb.com Matt Boros
            Votes:
            0 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated: