按最接近字段的日期对Mongodb查询中的文档进行排序

时间:2014-07-15 15:47:54

标签: python mongodb sorting date

我在mongodb中有一系列代表过去和即将发生的事件的文档。文档中有两个日期字段,' start'并且'结束'这是bson ISODATE对象。我正在进行查找查询,以获取所有已结束不超过3天的事件。

db.events.find({'end': {'$gte': datetime.utcnow() - timedelta(days=3)})

如何根据今天和事件的结束日期时间之间的时间(和日期)对此查询的响应进行排序。换句话说,2天前结束的事件应该发生在与现在2天后发生的事件大致相同的位置。这很重要,因为我不想先显示已经发生的所有事件,也不想先显示将来发生的事件。

2 个答案:

答案 0 :(得分:3)

如果我理解正确,您希望按今天和事件结束日期之间的时间差来排序。因此,如果您明天有一个活动,昨天有一个活动,前一天有一个活动,那么您希望他们进入的活动是:

  1. 明天的活动
  2. 昨天的事件
  3. 前天的事件
  4. 假设1和2可以互换,具体取决于实际的时差。

    这绝对可以通过MongoDB的聚合框架来完成。它的工作原理如下:

    1. 匹配在特定时间段内结束的文档。
    2. 在新字段中预测每个事件的今天和结束时间之间的差异(例如timeDelta)。
    3. 由于MongoDB没有聚合框架的绝对运算符,请执行一些条件检查以获取时间增量的绝对值并将其投影到新字段,例如absTimeDelta
    4. absTimeDelta排序。
    5. 所以看起来应该是这样的:

      db.events.aggregate([
          { '$match':
              { 'end':
                  { '$gte': datetime.utcnow() - timedelta(days=3) } 
              }
          },
          { '$project':
              {
                  'timeDelta': { 
                      '$subtract': ['$end', datetime.utcnow()]
                  }
              }
          },
          { '$project':
              {               
                  'absTimeDelta' : { 
                      '$cond' : [
                          { '$lte': ['$timeDelta', 0] },
                          { '$multiply' : ['$timeDelta', -1 ] },
                          '$timeDelta'
                      ]
                  }
              }
          },
          { '$sort':
              {
                  'absTimeDelta' : 1
              }
          }
      ])
      

      编辑:在MongoDB版本3.2中,this JIRA ticket已修复,引入了$abs operator。这意味着可以删除第二个$project,并且可以更新第一个'$subtract': ['$end', datetime.utcnow()]。您可以使用$abs: { '$subtract': ['$end', datetime.utcnow()] }而不是{{1}}。

答案 1 :(得分:0)

我现在没有看到任何方式可以让MongoDB为您执行此操作mongo does not support, for the moment, sorting using a function

但是,如果您的范围始终以当天为中心,为什么不每晚更新一个字段,将时间值存储在当天和事件之间?通过这种方式,您可以对其进行索引并对其进行排序。如果您保留多年的数据,您可能只想更新几周的数据,以获得固定时间更新,而不是随着数据增长而增长。