** 更新 **
Hello MongoDB-Experts,
我是一名软件开发人员,我对MongoDB没有多少经验。
我想在$ addToSet字段中对某些值进行排序。我基本上想要对$ group中的“firmen”(公司)进行排序。我怎么能这样做?
非常感谢您的帮助。
t.koelpin
这是我使用的PHP代码:
$sumQuery = array(
array(
'$match' => array(
'startzeit' => array(
'$gte' => new MongoDate(strtotime("2015-01-01 01:00:00")),
'$lte' => new MongoDate(strtotime("2015-01-01 08:00:00"))
)
)
),
array(
'$group' => array(
'_id' => array(
'portal' => '$portal',
'protokoll' => '$protokoll'
),
'daten' => array(
'$addToSet' => array(
'firmen' => '$firma'
)
),
'count' => array(
'$sum' => 1
)
)
),
array(
'$sort' => array(
'_id' => 1
)
),
array(
'$project' => array(
'_id' => 0,
'portal' => '$_id.portal',
'protokoll' => '$_id.protokoll',
'firmen' => '$daten.firmen',
'connections' => '$count'
)
)
);
这是我未分类的PHP输出:
答案 0 :(得分:1)
如@Neil answer以及此Jira Ticket sets
中所述,将无序。
延伸到Neil的答案,这可以通过以下步骤来实现:
Unwind
集合。Sort
基于该字段。Group
字段$push
。由于unwinding
和grouping
不会更改结果的顺序,唯一的挑战是保留Connections
的值。这可以使用$first
或$max
运算符来实现。
这是修改后的PHP代码来实现这一目标。
$sumQuery = array(
array(
'$match' => array(
'startzeit' => array(
'$gte' => new MongoDate(strtotime("2015-01-01 01:00:00")),
'$lte' => new MongoDate(strtotime("2015-01-01 08:00:00"))
)
)
),
array(
'$group' => array(
'_id' => array(
'portal' => '$portal',
'protokoll' => '$protokoll'
),
'daten' => array(
'$addToSet' => array(
'firmen' => '$firma'
)
),
'count' => array(
'$sum' => 1
)
)
),
//Unwinding daten.firmen
array('$unwind' => '$daten.firmen'),
//Sorting the values
array(
'$sort' => array(
'daten.firmen' => 1
)
),
//$push creates an array so the sorted order is preserved
array(
'$group' => array(
'_id' => array(
'portal' => '$_id.portal',
'protokoll' => '$_id.protokoll'
),
'daten' => array(
'$push' => array(
'firmen' => '$daten.firmen'
)
),
'count' => array(
'$max' => '$count'
)
)
),
array(
'$sort' => array(
'_id' => 1
)
),
array(
'$project' => array(
'_id' => 0,
'portal' => '$_id.portal',
'protokoll' => '$_id.protokoll',
'firmen' => '$daten.firmen',
'connections' => '$count'
)
)
);
PS:我不确定PHP的语法。请验证并修复任何小错误。
答案 1 :(得分:1)
真正的情况是,当然“套装”不会被认为是以任何方式进行排序,所以如果您希望订购这些元素,那么您需要以不是“集合”的方式对待它们。
优于“展开”由$addToSet
生成的数组,对于要包含在数组中的值,最初只是$group
,作为分组键的一部分。根据定义,分组键中的任何内容都是“不同”值,因此,如果您先$group
,那么您可以在$group
处理元素{{1}之后再次$sort
来“卷起”数组}。
这将节省大量开销,首先使用$addToSet
汇总数组,然后再次“去规范化”以便对内容进行排序,因为这可能非常昂贵:
$sumQuery = array(
array(
'$match' => array(
'startzeit' => array(
'$gte' => new MongoDate(strtotime("2015-01-01 01:00:00")),
'$lte' => new MongoDate(strtotime("2015-01-01 08:00:00"))
)
)
),
array(
'$group' => array(
'_id' => array(
'portal' => '$portal',
'protokoll' => '$protokoll',
'daten' => '$firmen'
),
'count' => array(
'$sum' => 1
)
)
),
array(
'$sort' => array(
'_id' => 1
)
),
array(
'$group' => array(
'_id' => array(
'portal' => '$_id.portal',
'protokoll' => '$_id.protokoll'
),
'daten' => array( '$push' => '$_id.daten'),
'count' => array(
'$sum' => '$count'
)
)
),
array(
'$project' => array(
'_id' => 0,
'portal' => '$_id.portal',
'protokoll' => '$_id.protokoll',
'firmen' => '$daten',
'connections' => '$count'
)
)
);
另请注意,如果您期望来自$project
阶段的某个“字段顺序”,则之前的阶段中不会出现任何字段名称,否则MongoDB只会将该输出“复制”到较早的文档中作为优化的位置。
通常建议不在您的管道末尾使用这样的$project
阶段,并接受返回的结果。这样做会为返回的结果添加一个额外的传递,以便进行字段重命名。因此,如果这里不需要计算,那么为了重新设置字段命名,你只需要花费大量的内存和CPU周期。
通常在收到结果的客户端代码中处理的比通过强制聚合管道执行它更好。但是,如果您$group
分两个阶段,首先处于更广泛的级别并且中间有$sort
,那么这是返回“不同”列表的最佳方式,而不会导致性能损失{{ 1}}然后再次重新分组结果。