Brian
Brian

Reputation: 395

Why is this Mongo query returning strange results?

I am using Node and MongoDB for an api. I'm trying to get results from the database that are filtered according to a device id (which is working just fine) as well as according to a timestamp integer. The user has the option of setting a start time, end time, both, or neither. All of the data seems to sending correctly, but the results are weird and seem illogical, so I'm obviously doing something wrong.

Here is the call being made to the databse:

exports.findByDeviceId = (id, start, end, cb) => {
  // start and end times provided
  if (start !== undefined && end !== undefined) {
    let query = db.entries.find({
      $and: [
        {device_id: id},
        {timestamp: {$gte: start}},
        {timestamp: {$lte: end}}
      ]
    }).sort({index: 1})
    console.log('start and end')
    query.toArray((err, myEntries) => {
      if (err) return cb(err, null)
      else {
        return cb(null, myEntries)
      }
    })
    // only start time provided
  } else if (start !== undefined && end === undefined) {
    let query = db.entries.find({
      $and: [
        {device_id: id},
        {timestamp: {$gte: start}}
      ]
    }).sort({index: 1})
    console.log('only start')
    query.toArray((err, myEntries) => {
      if (err) return cb(err, null)
      else {
        return cb(null, myEntries)
      }
    })
    // only end time provided
  } else if (start === undefined && end !== undefined) {
    let query = db.entries.find({
      $and: [
        {device_id: id},
        {timestamp: {$lte: end}}
      ]
    }).sort({index: 1})
    console.log('only end')
    query.toArray((err, myEntries) => {
      if (err) return cb(err, null)
      else {
        return cb(null, myEntries)
      }
    })
    // no time constraints provided  WORKS CORRECTLY
  } else {
    db.entries.find({device_id: id}).sort({index: 1}).toArray((err, myEntries) => {
      console.log('no start, no end')
      if (err) return cb(err, null)
      else {
        return cb(null, myEntries)
      }
    })
  }
}

To test this, I have two entries, one with a timestamp of 500, the second with a timestamp of 10000. Here are some of the strange results I'm getting:

?start=0   Both entries show up; as expected
?start=200 Only the entry with timestamp of 500 gets returned; both are expected
?start=700 Neither is returned; entry with timestamp 10000 is expected

?end=0     Neither entry is returned; as expected
?end=501   Both are returned; only entry with timestamp 500 is expected
?end=499   Only entry with 10000 is returned; Neither are expected

I haven't tested what happens when both a start and end are indicated.

If it matters, in the DB, the timestamp field is an Int32 field.

Any idea what I am doing wrong? It seems like the problem is with my use of $gte and $lte. Here are the docs for those. They seem pretty straightforward.

Any help is appreciated.

EDIT: Here is a sample entry:

{"_id":"xyz","index":1,"serial":"123","spent_c":0,"temp_c":2354,"direction":0,"battery":98,"timestamp":1519773832,"rh_c_1":0,"rh_c_2":0,"tp_c_1":2354,"tp_c_2":2374,"remain_c":10000,"device_id":"abc"}

Upvotes: 0

Views: 55

Answers (1)

Archit
Archit

Reputation: 961

The question is interesting, though it looks to me like instead of integer comparison, String comparison is happening for timestamp field.

500 > 200 but 10000 < 200 (in string comparison)

similarly for other cases. Please check with datatype is actually being used and you are casting the start and end to int correctly

Upvotes: 1

Related Questions