i have collection page and page has many widgets:
page collection :
_id
name
slug,
widget_codes
widget collection :
_id
name
code
type
product_ids
category_ids
product collection:
_id
name
type
category collection:
_id
name
type
for retrieve data i use like this:
public function getData($page) {
return $page->raw(function ($collection) use ($page) {
return $collection->aggregate([
[
'$lookup' => [
'from' => 'widgets',
'localField' => 'widget_codes',
'foreignField' => 'code',
'as' => 'widgets',
]
],
[
'$match' => ['slug' => $page->slug]
]
]);
});
}
it works perfect and get widget data now i want to get product and category data with widget using that widget has product_ids and category_ids what query can i use.
You can use pipeline in $lookup for subquery the multiple tables
public function getData($page) {
return $page->raw(function ($collection) use ($page) {
return $collection->aggregate([
[
'$match' => ['slug' => $page->slug]
],
[
'$lookup' => [
'from' => 'widgets',
"let"=> [ "widget_codes"=> "$widget_codes" ],
"pipeline"=> [
[ "$match"=> [ "$expr"=> [ "$in"=> ["$_id", "$$widget_codes"] ]]],
[
'$lookup' => [
'from' => 'category',
'localField' => 'category_ids',
'foreignField' => '_id',
'as' => 'categories',
]
],
[
'$lookup' => [
'from' => 'product',
'localField' => 'product_ids',
'foreignField' => '_id',
'as' => 'products',
]
]
],
'as' => 'widgets',
]
]
]);
});
}
Related
I'm trying to select data from few documents and output in nested arrays.
Aggregate:
$aggBuilder = $this->documentManager->getDocumentCollection(User::class);
$outputData = $aggBuilder->aggregate([
['$match' => [
'_id' => ['$in' => $usersId]
]
],
['$unwind' => '$articles'],
['$lookup' => [
'from' => 'articles',
'localField' => 'articles._id',
'foreignField' => '_id',
'as' => 'article',
]],
['$unwind' => '$article'],
['$lookup' => [
'from' => 'comments',
'localField' => 'comments._id',
'foreignField' => 'article_id',
'as' => 'article.comment'
]],
['$group' => [
'_id' => [
'id' => '$_id',
'name' => '$name',
'desc' => '$desc',
],
'articles' => ['$addToSet' => [
'id' => '$article._id',
'title' => '$article.title',
'content' => '$article.content',
'comments' => ['id' => $article.comment.id', 'content' => '$article.comment.content'],
]],
]]
],
[
'cursor' => [
'batchSize' => 101,
],
]);
dd($outputData->toArray());
The problem is in part where I try to in every article get collection of comments for this article.
Some reason output looks this:
'Andy Jones' = [
'Article First' = [
'id' = 'sdgdf76g8df',
'title' = 'First Article'
'content' = 'Contetn of article'
'comments' = [
'id' = [
'dfdh54gdfter',
'32gdfhfgh43et',
'34te3gdfgerdt'
],
'content' = [
'content for first article',
'content for second article',
'content for third article'
]
]
]
]
As you see comments are splited in two arrays. One for 'id' and one for 'content'.
What I want is separate array for every comment and in that array data from single comment. Like bellow:
'comments' = [
[0] = [
'id' = 'dfdh54gdfter',
'content' = 'Lorem ipsum 1',
],
[1] = [
'id' = 'dfdg4554er',
'content' = 'Lorem ipsum 2',
],
[2] = [
'id' = 'dfdh54gdfter',
'content' = 'Lorem ipsum 3',
],
]
Thank you.
I have two tables in mongodb database
activityCountTbl contains data like
{
"_id": ObjectId("5c234f7e3250041280000ca3"),
"activityId": ObjectId("5c0e27ee590a06bf08003c33"),
"weekgroupId": ObjectId("5bfbddbcbb2c5645f8001495"),
"squadronId": ObjectId("5bfc7b7ebb2c56c320002a0a"),
"attendingCount": NumberInt(6),
....
}
{
"_id": ObjectId("5c234f7e3250041280000ca3"),
"activityId": ObjectId("5c0e27ee590a06bf08003c33"),
"weekgroupId": ObjectId("5bfbddbcbb2c5645f8001496"),
"squadronId": ObjectId("5bfc7b7ebb2c56c320002a0a"),
"attendingCount": NumberInt(6),
....
}
squadronTbl contains data like
{
"_id": ObjectId("5c19ccb7590a060691000554"),
"squadronCode": "336",
"squadronName": "336TRS",
}
{
"_id": ObjectId("5c19ccb7590a060691000556"),
"squadronCode": "337",
"squadronName": "337TRS",
}
I am storing count details of a particular activity of a weekgroup in activityCountTbl. I am performing lookup on squadronTbl with activityCountTbl
for fetching squadrons details of a particular weekgroup. The below code is not working.
When I comment/delete the $query code, it fetches all the squadrons of all weekgroups.
$query = ["ActivityArray.weekgroupId" => new MongoDB\BSON\ObjectID("5bfbddbcbb2c5645f8001495"), "ActivityArray.funRun" => "Yes"];
$pipeline = array(
[
'$match' => $query
],
[
'$lookup' => [
'from' => 'activityCountTbl',
'localField' => '_id',
'foreignField' => 'squadronId',
'as' => 'ActivityArray'
]
],
['$project' => [
'_id' => 1.0,
'squadronName' => 1.0,
'ActivityArray' => 1.0
]],
);
return $this->db->squadronTbl->aggregate($pipeline)->toArray();
Please help !!!
$query = ["ActivityArray.weekgroupId" => new MongoDB\BSON\ObjectID("5bfbddbcbb2c5645f8001495"), "ActivityArray.funRun" => "Yes"]
$pipeline = array(
[
'$match' => []
],
[
'$lookup' => [
'from' => 'activityCountTbl',
'localField' => '_id',
'foreignField' => 'squadronId',
'as' => 'ActivityArray'
]
],
[
'$match' => $query
],
['$project' => [
'_id' => 1.0,
'squadronName' => 1.0,
'ActivityArray' => 1.0
]],
);
something like that
I have two collection rounds and summaries
A record in rounds looks like
{
"_id": "2018-04",
"name": "Round 2018-04"
}
A record in summaries look like
{
"phase": "round:2018-04",
"userId": NumberLong(66325),
}
I want to query summaries and lookup into rounds joining based on phase of summaries into _id of rounds
PROBLEM: It will be pretty simple if there was no prefix of round: in phase.
Is there anyway to do this?
This is my code so far.
$cursor = $this->mongo->selectCollection('summaries')->aggregate([
array('$match' => []),
array(
'$lookup' => [
'from' => 'rounds',
'localField' => 'phase',
'foreignField' => '_id',
'as' => 'roundDetail'
]
),
array(
'$unwind' => '$roundDetail',
),
array(
'$project' => [
'userId' => 1,
'roundDetail.name' => 1
]
)
]);
MongoDB version 3.4.16
You can use substrBytes to remove characters from the string.
$cursor = $this->mongo->selectCollection('summaries')->aggregate([
array('$match' => []),
array('$addFields' => [ 'phase' => [ '$substrBytes' => [ '$phase', 6, 7 ] ] ] ),
array(
'$lookup' => [
'from' => 'rounds',
'localField' => 'phase',
'foreignField' => '_id',
'as' => 'roundDetail'
]
),
array(
'$unwind' => '$roundDetail',
),
array(
'$project' => [
'userId' => 1,
'roundDetail.name' => 1
]
)
])
I have a collection studentTbl which contains records like
Record 1
"_id": ObjectId("5b45d89bbbc51e2c2c006973")
"first_name": "Pooja",
...
contact_details[
{
..
},
{
..
}
]
transport_details[
{
allotment_id:"68998546878",
..
status:"Inactive"
},
{
allotment_id:"25799856890",
..
status:"Active"
}
]
}
Record 2
"_id": ObjectId("5b45d89bbbc51e2c2533")
"first_name": "Poornima",
...
contact_details[
{
..
},
{
..
}
]
transport_details[
{
allotment_id:"68998546878",
..
status:"Inactive"
}
]
}
Record 3
"_id": ObjectId("5b45d89bbbc51e2c2c00646")
"first_name": "Poonam",
...
contact_details[
{
..
},
{
..
}
]
transport_details[
{
allotment_id:"68998546878",
..
status:"Inactive"
},
{
allotment_id:"25799856890",
..
status:"Active"
}
]
}
I am trying to tweak the below lines of code in order to fetch those students whose first_name or middle_name or last_name contains "poo" and inside the last element of embedded document transport_details, status should be "Active". How to write such a query which will find students on the name basis and traverse through the last element of embedded document transport_details and checks whether the status is active? For e.g in the above collection, pooja and poonam should be returned.
The code is like
// default if nothing is filled
$query = array("schoolId"=> new MongoDB\BSON\ObjectID($this->schoolId));
// if name = filled, class = null, year = null
if(!empty($this->name) && empty($this->academicYearName) && empty($this->programId))
{
$param = preg_replace('!\s+!', ' ', $this->name);
$arg = trim($param);
$query = array(
'$or' => array(
array("first_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("middle_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("last_name" => new MongoDB\BSON\Regex($arg, 'i')),
array("registration_temp_perm_no" => $arg)
),
"schoolId"=> new MongoDB\BSON\ObjectID($this->schoolId)
);
}
...
...
...
$pipeline = array(
array(
'$match' => $query
),
array(
'$lookup' => array(
'from' => 'programTbl',
'localField' => 'classId',
'foreignField' => '_id',
'as' => 'ClassDetails'
)
),
);
try
{
$cursor = $this->collection->aggregate($pipeline);
}
catch (Exception $e) {
}
return $cursor->toArray();
Note that the actual code contains more conditional $query variable...
You can use below query in 3.6.
array(
'$or' => array(
array("first_name" => new MongoDB\BSON\Regex("/poo/i")),
array("middle_name" => new MongoDB\BSON\Regex("/poo/i")),
array("last_name" => new MongoDB\BSON\Regex("/poo/i"))
),
"$expr" => array(
"$eq" => array(
array("$arrayElemAt" => array("$transport_details.status", -1)),
"Active"
)
)
);
You can add below stages in your pipeline
array(
"$match" => array(
"$expr" => array(
"$and" => [
array(
"$or" => [
array( "$eq" => [ array( "$strcasecmp" => [ "$first_name", "Poo" ] ), 1 ] ),
array( "$eq" => [ array( "$strcasecmp" => [ "$last_name", "Poo" ] ), 1 ] ),
array( "$eq" => [ array( "$strcasecmp" => [ "$middle_name", "Poo" ] ), 1 ] ),
],
),
array(
"$eq" => [
array( "$arrayElemAt" => [ array( "$slice"=> [ "$transport_details.status", -1 ] ), 0 ] ),
"Active"
]
)
]
)
)
)
I have code like this:
$users = User::raw(function ($collection) use($profession, $userId, $skip, $pageSize) {
return $collection->aggregate([
[
'$lookup' => [
'from' => 'user_profile',
'localField' => 'uid',
'foreignField' => 'user_id',
'as' => 'profile'
]
],
[
'$match' => [
'profile.field_of_work' => $profession['id'],
'uid' => ['$ne' => $userId]
],
],
['$skip' => $skip],
['$limit' => $pageSize]
]);
});
from there, how to add where clause like this:
::where('name', 'like', '%test%');
I dont know how to using lookup in mongodb and I just know the basic pattern of eloquent.
Thank you