以下是我的文档的外观:
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
的{strong> 0
的每个元素在[{1}}开启并在24*60*60
关闭的商店(午夜后的几秒钟。
我尝试使用$all
和$elemMatch
,但是如果数组中至少有一个元素符合给定条件(我不需要),它们可以用于我需要匹配的情况
答案 0 :(得分: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天内匹配。您可以进行更多匹配,仅在opens
和0
closes
找到86400
。
结果:
{
"result" : [
{
"_id" : {
"name" : "Kindle store",
"opens" : 0,
"closes" : 86400
},
"total" : 7
}
],
"ok" : 1
}
答案 1 :(得分: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()