Как запросить документы с помощью встроенного массива и отсортировать их
У меня проблема с запросом документов с помощью embedMany.
Это мои документы, где пользователь встраивает много групп (которые я называю userGroups).
class User {
/**
* @MongoDB\Id
*/
protected $id;
/**
* @MongoDB\Field(type="string")
*/
protected $name;
/**
* @MongoDB\EmbedMany(targetDocument="Group", strategy="setArray")
* @var UserGroups[]
*/
protected $userGroups;
}
class UserGroup {
/**
* @MongoDB\NotSaved
* @MongoDB\ReferenceOne(targetDocument="Group")
* @var Group
*/
protected $group;
/**
* @MongoDB\Field(type="string")
* @var string
*/
protected $type;
/**
* @MongoDB\Field(type="date")
* @var \DateTime
*/
protected $joinedAt;
}
Это документы БД в коллекции User:
{
"_id" : ObjectId("56de151b821b16ac02310a25"),
"name" : "Some user name",
"userGroups" : [
{
"group" : DBRef("groups", ObjectId("5705157244ae89863aaeb725"), "some group name"),
"type" : "T1",
"joinedAt" : ISODate("2016-05-13T19:59:43.000+0000")
},
{
"group" : DBRef("groups", ObjectId("571498f7821b16100c5bcc58"), "some other group name"),
"type" : "T1",
"joinedAt" : ISODate("2016-05-21T20:07:26.000+0000")
},
{
"group" : DBRef("groups", ObjectId("57348618c67940a0528b4567"), "some other group name T2"),
"type" : "T2",
"joinedAt" : ISODate("2016-05-30T18:07:39.000+0000"),
}
]
}
{
"_id" : ObjectId("287sd3d728as56dnsdu2hsds782nsdsd"),
"name" : "Some other user name",
"userGroups" : [
{
"group" : DBRef("groups", ObjectId("5705157244ae89863aaeb725"), "some group name"),
"type" : "T2",
"joinedAt" : ISODate("2016-05-13T19:59:43.000+0000")
},
{
"group" : DBRef("groups", ObjectId("57348618c67940a0528b4567"), "some other group name T2"),
"type" : "T2",
"joinedAt" : ISODate("2016-05-30T18:07:39.000+0000"),
}
]
}
Как я могу запросить пользователей в group
с ID '5705157244ae89863aaeb725'
и введите "T1"
? Следующий запрос в коллекции Users доставляет обоих пользователей, и он должен доставлять только первого, который имеет группу с ID '5705157244ae89863aaeb725'
и введите "T1"
{ userGroups: { $elemMatch:
{ "group.$id": ObjectId("5705157244ae89863aaeb725"), "type": "T1" } }}
Но не могу отсортировать их по joinedAt
поле
1 ответ
Для сортировки внутреннего поля массива вам нужно использовать структуру агрегации: этот пример содержит шаги, и вы можете удалить их, чтобы увидеть, как изменяется документ
var unwind = {
$unwind : "$userGroups"
}
var match = {
$match : {
"userGroups.group.$id" : ObjectId("5705157244ae89863aaeb725"),
"userGroups.type" : "T1"
}
}
var sort = {
$sort : {
"userGroups.joinedAt" : -1
}
}
var reGroup = {
$group : {
_id : {
id : "$_id",
name : "$name"
},
userGroups : {
$push : "$userGroups"
}
}
}
var reShapeDocument = {
$project : {
_id : "$_id.id",
name : "$_id.name",
userGroups : 1
}
}
//шаг 1
db.coll.aggregate([match ])
//шаг 2
db.coll.aggregate([match, unwind ])
//шаг 3
db.coll.aggregate([match, unwind, match, ])
// шаг 4
db.coll.aggregate([match, unwind, match, sort, ])
// шаг 5,6
db.coll.aggregate([match, unwind, match, sort, reGroup, reShapeDocument])
1 и 3 выбирают только критерии соответствия документов, 2 - разматывает элементы массива для разделения документов, 4 - выполняет сортировку, 5 и 6 используются для восстановления предыдущей фигуры