我正在尝试为网站设置消息收件箱,并且需要将用户(发件人或收件人)的所有文档分组到线程中。 消息集合中充满了这样的文档:
{
"_id" : ObjectId("4fe8d8ac0a6d2ad9350000d9"),
"message" : "booo",
"recipient" : {
"user_id" : ObjectId("4fd9f0600a6d2ac94f000003"),
"viewed" : 1
},
"sender" : {
"user_id" : ObjectId("4fdb3b780a6d2a9d29000047"),
},
"thread" : "c03a4e49348d009f4ddd8aae325128e1"
"date_sent" : ISODate("2012-06-25T21:31:24.230Z"),
}
我能够使用 mongo 的 group 函数来获得所需的结果,但您无法对 group 进行排序或限制,因此理想情况下我想使用聚合框架,但我无法获得所需的结果。 基本上我需要这样做:
$groupBy = array(
'thread' => 1,
);
$initial = array('count' => 0);
$reduce = "function (obj, prev) {
prev.count++;
prev.message = obj.message;
prev.sender = obj.sender.user_id;
prev.recipient = obj.recipient.user_id;
prev.date_sent = obj.date_sent;
prev.viewed = obj.recipient.viewed;
}";
$condition = array(
'$or' => array(
array('sender.user_id' => new MongoId($options['user_id'])),
array('recipient.user_id' => new MongoId($options['user_id']))
)
);
return $this->_collection->group($groupBy, $initial, $reduce, $condition);
使用聚合框架,但我没有得到我需要的结果......基本上我有这个:
$condition = array(
'$or' => array(
array('sender.user_id' => new MongoId($options['user_id'])),
array('recipient.user_id' => new MongoId($options['user_id']))
)
);
$returnFields = array(
'message' => 1,
'sender.user_id' => 1,
'recipient.user_id' => 1,
'date_sent' => 1,
'thread' => 1,
);
$sort = array('date_sent' => 1);
$groupBy = array('_id' => '$thread');
$input = array(
'aggregate' => $this->_collectionName,
'pipeline' => array(
array('$project' => $returnFields),
array('$match' => $condition),
array('$group' => $groupBy),
array('$sort' => $sort),
)
);
return $this->_db->command($input);
它只是返回线程,就像它忽略了我的$project一样......知道吗?
我已经想通了。不太确定为什么$project不携带,但是,我可以使用$first运算符来选择$group语句中的字段
$condition = array(
'$or' => array(
array('sender.user_id' => new MongoId($options['user_id'])),
array('recipient.user_id' => new MongoId($options['user_id']))
)
);
$sort = array('date_sent' => -1);
$groupBy = array(
'_id' => '$thread',
'sender' => array('$first' => '$sender.user_id'),
'recipient' => array('$first' => '$recipient.user_id'),
'date_sent' => array('$first' => '$date_sent'),
'message' => array('$first' => '$message'),
'viewed' => array('$first' => '$recipient.viewed'),
);
$input = array(
'aggregate' => $this->_collectionName,
'pipeline' => array(
array('$match' => $condition),
array('$sort' => $sort),
array('$group' => $groupBy),
array('$sort' => $sort),
)
);
return $this->_db->command($input);
基本上,我需要匹配正确的文档,对它们进行排序,以便最新的消息排在第一位,执行$group,我可以在其中使用 $first 运算符选择字段,然后再次对它们进行排序,以便它们按正确的顺序排列。 不认为这是必要的,但这似乎可以正常工作。