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

How to get the previous mongoDB document from a compound index

    • Type: Icon: Question Question
    • Resolution: Duplicate
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 2.2.0
    • Component/s: Internal Client
    • Labels:
    • Environment:
      Windows 7 64 bit SP1

      I asked this at mongo-usr, mongo-dev and Stack Overflow with no luck. I may be obtuse and am missing something fundamentally simple.

      Given this data with a unique compound index:

      db.employees.drop()
      db.employees.insert( { employeenum : 1, check : "A" } )
      db.employees.insert( { employeenum : 1, check : "B" } )
      db.employees.insert( { employeenum : 2, check : "A" } )
      db.employees.insert( { employeenum : 2, check : "B" } )
      db.employees.insert( { employeenum : 2, check : "C" } )
      db.employees.insert( { employeenum : 5, check : "E" } )
      db.employees.insert( { employeenum : 6, check : "A" } )
      db.employees.ensureIndex( { employeenum: 1, check : 1 }, {unique: true} )
      

      If I want the next document in the index after {{

      { employeenum : 5, check : "E" }

      }}. I can do this:

      db.employees.find({ query: { $or: [ { employeenum: { $gt: 5 } }, { check: { $gt: "E" } } ] }, $min: { employeenum: 5, check: "E" }, $maxScan: 2 })
      

      which returns {{

      { employeenum : 6, check : "A" }

      }}.

      But how do I traverse backwards from {{

      { employeenum : 5, check : "E" }

      }}? How do I fetch {{

      {employeenum : 2, check : "C" }

      }}? The way I am doing it:

      { query: { $or: [ { employeenum: { $lt: 5 } }, { check: { $lt: "E" } } ] }, $hint: { employeenum: -1, check: -1 }, $min: { employeenum: 5, check: "E" }, $maxScan: 2 }
      

      requires a reverse index, a very inefficient solution. Is there a better way? B-tree indexes are bi-directional.

      One suggested:

      db.Emp.find({$or:[{employeenum{$lt:5}}]}).sort({employeenum:-1,check:-1}).limit(1)
      

      And yes that will gets me 2-C. Now, how to go from 2-C to 2-B? This:

      db.employees.find({$or:[{employeenum:{$lt:2}},{check:{$lt:"C"}}]}).sort({employ??eenum:-1,check:-1}).limit(1)
      

      returns {{

      {"employeenum" : 6, "check" : "A"}

      }} I need a general way to traverse the index from a point on the index. I am using the C++ driver but using the shell here for illustration. We are developing a rapid development tool using mongoDB as the underlying database. This is a (presumably) simple use case: A window displays a single document from a collection with a compound index. The user presses a button to display the next document using the compound index. Or another button to display the previous.

      I did try:

      db.employees.find({ query: { $or: [ { employeenum: { $lt: 5 } }, { check: { $lt: "E" } } ] }, $max: { employeenum: 5, check: "E" }, orderby: { employeenum: -1, check: -1 }, $maxScan: 2,  $explain: false })
      

      But that crashed the server every time which raises a concern that a shell users could crash the server with an (apparently) malformed query in a mission critical application such as ours.

            Assignee:
            thomas.rueckstiess@mongodb.com Thomas Rueckstiess
            Reporter:
            therefore George Thompson
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: