我的数据看起来像这样:
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func NextViewcontroller(sender: AnyObject)
{
let startVC = self.viewControllerAtIndex(0) as ContentViewController
let viewControllers = NSArray(object: startVC)
self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: .Forward, animated: true, completion: nil)
}
func viewControllerAtIndex(index: Int) -> ContentViewController
{
if ((self.pageTitles.count == 0) || (index >= self.pageTitles.count)) {
return ContentViewController()
}
let vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.imageFile = self.pageImages[index] as! String
vc.titleText = self.pageTitles[index] as! String
vc.pageIndex = index
return vc
}
// MARK: - Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
let vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == 0 || index == NSNotFound)
{
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == NSNotFound)
{
return nil
}
index++
if (index == self.pageTitles.count)
{
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.pageTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}
}
我的聚合/群组如下所示:
{
"_id" : "9aa072e4-b706-47e6-9607-1a39e904a05a",
"customerId" : "2164289-4",
"channelStatuses" : {
"FOO" : {
"status" : "done"
},
"BAR" : {
"status" : "error"
}
},
"channel" : "BAR",
}
所以基本上使用示例数据,该组应该给我一个按以下方式分组的组:
{
"_id" : {
"customerId" : "$customerId",
"channel" : "$channel",
"status" : "$channelStatuses[$channel].status"
},
"count" : {
"$sum" : 1
}
}
但是我不能在聚合/组中使用[] -indexing。我该怎么做呢?
答案 0 :(得分:2)
使用.aggregate()
无法获得当前结构所需的结果。你"可能"更改结构以使用数组而不是命名键,操作实际上非常简单。
所以使用如下文档:
{
"_id" : "9aa072e4-b706-47e6-9607-1a39e904a05a",
"customerId" : "2164289-4",
"channelStatuses" : [
{
"channel": "FOO",
"status" : "done"
},
{
"channel": "BAR",
"status" : "error"
}
],
"channel" : "BAR",
}
然后,您可以使用$filter
,$map
和$arrayElemAt
在现代版本中执行此操作:
{ "$group": {
"_id": {
"customerId" : "$customerId",
"channel" : "$channel",
"status": {
"$arrayElemAt": [
{ "$map": {
"input": { "$filter": {
"input": "$chanelStatuses",
"as": "el",
"cond": { "$eq": [ "$$el.channel", "$channel" ] }
}},
"as": "el",
"in": "$$el.status"
}},
0
]
}
},
"count": { "$sum": 1 }
}}
较旧版本的MongoDB将需要$unwind
来访问匹配的数组元素。
在MongoDB 2.6中,您仍然可以预先过滤"展开前的数组:
[
{ "$project": {
"customerId": 1,
"channel": 1,
"status": {
"$setDifference": [
{ "$map": {
"input": "$channelStatuses",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.channel", "$channel" ] },
"$$el.status",
false
]
}
}},
[false]
]
}
}},
{ "$unwind": "$status" },
{ "$group": {
"_id": {
"customerId": "$customerId",
"channel": "$channel",
"status": "$status"
},
"count": { "$sum": 1 }
}}
]
之前的任何事情你都要过滤"在$unwind
后改为:
[
{ "$unwind": "$channelStatuses" },
{ "$project": {
"customerId": 1,
"channel": 1,
"status": "$channelStatuses.status",
"same": { "$eq": [ "$channelStatuses.status", "$channel" ] }
}},
{ "$match": { "same": true } },
{ "$group": {
"_id": "$_id",
"customerId": { "$first": "$customerId" },
"channel": { "$first": "$channel" },
"status": { "$first": "$status" }
}},
{ "$group": {
"_id": {
"customerId": "$customerId",
"channel": "$channel",
"status": "$status"
},
"count": { "$sum": 1 }
}}
]
在比MongoDB 2.6更小的版本中,您还需要$project
两个字段之间的相等性测试结果,然后$match
结果处于单独的阶段。您可能还会注意到"两个" $group
个阶段,因为第一个阶段通过"channel"
累加器删除了过滤后的$first
值的任何可能重复项。以下$group
与上一个列表中的完全相同。
但是,如果你不能改变结构和需要"灵活"如果您不能提供每个名称的键匹配,那么您必须使用mapReduce:
db.collection.mapReduce(
function() {
emit({
"customerId": this.customerId,
"channel": this.channel,
"status": this.channelStatuses[this.channel].status
},1);
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
当然,你可以使用那种符号