3

这是我的文档的外观:

nookstore = {
     "name": "Nook store",
     "categories": ["bookstore"],
     "working_hours": [
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 8*60*60, "closes": 21*60*60 },
        {"opens": 9*60*60, "closes": 20*60*60 },
     ]
  }

  ...

kindlestore = {
     "name": "Kindle store",
     "categories": ["bookstore"],
     "working_hours": [
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
        {"opens": 0, "closes": 24*60*60 },
     ],
  }

我正在寻找 24 小时营业的商店,即每个元素working_hours营业时间0和关闭时间24*60*60(午夜后几秒)的商店。

我尝试使用$alland $elemMatch,但如果数组的至少一个元素与给定条件匹配(我不需要),它们在我需要匹配的情况下工作。

4

2 回答 2

1

虽然我认为如果您修改架构以将特殊状态作为另一个字段 ( ) 包含这将是最好的open24hours,但您可以使用聚合框架来查找匹配项。

db.stores.aggregate({$unwind : '$working_hours' }, 
   { $group : { 
       _id : { 
         name: '$name', 
         opens: '$working_hours.opens', 
         closes: '$working_hours.closes' }, 
      total: { $sum : 1 }
      }
  }, 
  { $match : { total : 7 } })

这会展开打开的小时数,然后按名称分组,打开和关闭时间,从而形成一个独特的组合,然后总计每个组合的匹配数。如果总共有 7 个,那么它在所有 7 天都匹配。您可以进行更多匹配以仅找到opensat0closesat 86400

结果:

{
    "result" : [
            {
                    "_id" : {
                            "name" : "Kindle store",
                            "opens" : 0,
                            "closes" : 86400
                    },
                    "total" : 7
            }
    ],
    "ok" : 1
}
于 2013-10-24T20:17:04.413 回答
1

您可以使用聚合框架来做到这一点,可能有多种方式。这只是分组以查找唯一的打开/关闭时间,并在午夜到午夜的单个打开/关闭时间最后匹配。

db.stores.aggregate(
  [ 
    { $unwind: '$working_hours' },
    { $group: { _id: '$name', times: { $addToSet: '$working_hours' } } },
    { $unwind: '$times' },
    { $group: { _id: '$_id', times: { $push: '$times' }, cnt: { $sum: 1 } } },
    { $match: { 'times.opens': 0, 'times.closes': 86400, cnt: 1 } }
  ]
)

编辑:另一个可能更好的选择是尽早匹配,而不必对不相关的值进行分组;

db.stores.aggregate(
  [
    { $unwind: '$working_hours' },
    { $match: { 'working_hours.opens': 0, 'working_hours.closes': 86400 } },
    { $group: { _id: '$name', cnt: { $sum: 1 } } },
    { $match: { 'cnt': 7 } }
  ]
)

EDIT2:也可以在没有聚合框架的情况下通过查找所有没有不匹配时间的商店来完成;

db.stores.find({
  'working_hours': { 
    $not: { 
      $elemMatch: {
        $or:[ { 'opens': { $ne: 0 } }, { 'closes': { $ne: 86400 } } ]
      }
    }
  }
}).pretty()
于 2013-10-24T20:18:36.953 回答