【问题标题】:Mongodb aggregation stage $match results with timeout errorMongodb 聚合阶段 $match 结果超时错误
【发布时间】:2018-03-15 23:09:06
【问题描述】:

users_table 中大约有 9000 个用户,订单数最多的用户有大约 300 个订单。

当我使用下面的代码查询时,一切正常,直到 $match 阶段。它需要超过 20 秒,因此查询导致超时错误。我知道我可以增加消除该错误的时间,但我想知道为什么一个简单的$match 阶段需要很长时间?

db.getCollection('users_table').aggregate([
{
// user.id field is related to order.user_id field 
  '$lookup': {
    'from': 'orders_table',
    'localField': 'id',
    'foreignField': 'user_id',
    'as': 'orders'
  }
},
{
// I keep user.id and the delivered orders
  '$project': {
    'id': 1,
    'filtered_orders': {
      '$filter': {
        'input': '$orders',
        'as': 'order',
        'cond': {'$eq':['$$order.status', 'delivered']}
      }
    }
  }
},
{
// get rid of _id and get delivered order count as well as user.id
  '$project': {
    '_id': 0,
    'id': 1,
    'order_count': {'$size': '$filtered_orders'}
  }
},
{
// get order_count field between 200 and 350
  '$match': {
    'order_count' : {'$gte': 200, '$lte': 350}
  }
}
])

【问题讨论】:

  • 您是否尝试在 user_id 和 id 上添加索引?
  • 不,我没有,因为我还不知道怎么做 :)
  • db.users_table.createIndex( { id: 1 }, { background: true } ) db.orders_table.createIndex( { user_id: 1 }, { background: true } )
  • 在这些字段上创建索引解决了这个问题。如果您将评论添加为答案,我可以接受。谢谢!

标签: mongodb robo3t


【解决方案1】:

考虑添加索引

db.users_table.createIndex( { id: 1 }, { background: true } )
db.orders_table.createIndex( { user_id: 1 }, { background: true } )

【讨论】:

    【解决方案2】:

    试试这个查询。还要确保orders_table中的“状态”被索引

    db.getCollection('orders_table').aggregate([
      {
        '$match': {
          'status' : 'delivered'
        }
      },
      {
        $group:{
          _id:'$user_id',
          order_count: { $sum: 1 }
          user_id:'$user_id',
        }
      },
      {
        '$match': {
          'order_count' : {'$gte': 200, '$lte': 350}
        }
      },
    ])

    【讨论】:

    • 不幸的是我不能使用这个解决方案。这样我就无法获取订单数为零的用户。另外,我对索引一无所知:/我会尝试学习和使用它。谢谢。
    • 在您质疑您的最后一场比赛时,请删除所有少于 200 名的用户。如果您希望所有用户不要进行最后一场比赛
    • 我不想要所有的用户。 $match 限制 200 和 350 只是这个问题的随机数(顺便说一下,您的解决方案适用于它们)。但是,如果我想获取订单计数在 0 到 25 之间的用户({'$gte': 0, '$lte': 25}),您的查询将不包括订单计数为 0 的用户。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 2019-07-20
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多