Mongo DB aggregate query in php [duplicate] - php

This question already has answers here:
How do I do a "NOT IN" query in Mongo?
(4 answers)
Aggregation filter after $lookup
(1 answer)
Closed 4 years ago.
I am new in MongoDB so facing issue in making join query in mongo please help
I have two collection "user" and "user_login_details"
Previously I have below query to fetch record from single collection
$data = $this->mongodb->select()->where(array('instituteId' => $instituteId))->where_not_in('type', array($instituteAdmin))->get('user');
Now I want to fetch records from two collection "user" have single row and for that row multiple entries of login detail present in "user_login_details" collection.
I try with aggregate as below
db.user.aggregate([
{$match: { instituteId: '5954ee6dcf2169d50d51b88d'} },
{
$lookup:
{
from: "user_login_details",
localField: "_id",
foreignField: "user_id",
as: "user_login_details"
}
}
]).pretty()
But need one more condition as per my first query in php
->where_not_in('type', array($instituteAdmin))
How I can add this in aggregate query.
Also above query will return data with multiple login details as below.
{
"_id" : ObjectId("5954ee6dcf2169d50d51b88e"),
"email" : "abc#gmail.com",
"instituteId": "5954ee6dcf2169d50d51b88d",
"type": "Institute Admin"
"user_name" : "SA-011",
"religion" : "",
"caste" : "",
"bloodGroup" : "",
"groups" : "",
"reset_password" : NumberLong(1),
"aws_arn" : "",
"user_login_details" : [
{
"_id" : ObjectId("5b069955df05aeda0f8b4568"),
"user_id" : ObjectId("5954ee6dcf2169d50d51b88e"),
"ip" : "::1",
"my_session_id" : "3199d6fd6ecfef1ec63bc1760115d116",
"login_time" : ISODate("2018-05-24T10:52:05Z"),
"logout_time" : ISODate("2018-05-24T11:04:47Z")
},
{
"_id" : ObjectId("5b069c52df05ae6e358b4567"),
"user_id" : ObjectId("5954ee6dcf2169d50d51b88e"),
"ip" : "::1",
"my_session_id" : "b2d33ea8bc7cc3bb8090fc1dd15f7371",
"login_time" : ISODate("2018-05-24T11:04:50Z"),
"logout_time" : ""
}
]
}
I need only latest record from "user_login_details" collection.
Please help by creating query in PHP as I used "CodeIgniter MongoDB Active Record Library".
Thanks in advance.

Related

How to search multiple collections in mongoDB [duplicate]

This question already has answers here:
How to Match on Joined Collections Using Laravel and MongoDB?
(1 answer)
How to join to two additional collections with conditions
(1 answer)
Aggregate $lookup Total size of documents in matching pipeline exceeds maximum document size
(2 answers)
Closed 4 years ago.
I have 2 collections in mongoDB namely product and author . Now the product collection has an object called the detail which has the title and other details whereas the author table has details regarding the author . Now i am trying to make a search that finds both title and author .. For eg: if the title is matched the details of that product should be listed and if the author is matched then again the details of that product should be shown. The author_id is a foreign_key in the product collection and the _id is a primary key in the author collection.
Below is my collection
The Product Collection
{
"_id" : ObjectId("5af2bd44a003533a8abf4e56"),
"product_type_id" : "5ae834807ae0d9538e45ab45",
"date_added" : "2018-03-12 12-3-54",
"status" : 1,
"detail" : {
"title" : "The random title",
"author_id" : "5af2c401a003533a8abf4e57",
"test_id" : 12345,
"description" : "I have a mongoDB collection with f rows",
"mrp" : 200,
"binding" : "sd",
"language" : "English",
"isbn" : NumberLong("9788700631625"),
"isbn_10" : 747532745,
"ean" : 897655,
"pages" : 200
}
}
This is the author collection
{
"_id" : ObjectId("5af2c401a003533a8abf4e57"),
"name" : "Dan Brown",
"test_id" : 12345
}
So far i have to search on the collections independently . But not together
For author search
db.author.aggregate
([{
"$match":
{
"name":"Dan Brown"
}
},
{
"$lookup":
{
"from": "product",
"localField": "test_id",
"foreignField": "detail.test_id",
"as": "users"
}
}
]
).pretty();
And title has been accessed using the normal find() method
EDIT 1:
So this is what i have tried so far. Is this the right approach . Btw it's still not working though
db.product.aggregate
(
[
{
"$match":
{
detail.title : 'The random title'
}
},
{
"$lookup":
{
"from": "author",
"localField": "test_id",
"foreignField": "detail.test_id",
"as": "tb2"
}
},
{
"$unwind": "$tb2"
},
{
"$match":
{
"tb2.name": "agent"
}
}
]
);

how to count of embedded mongodb php? [duplicate]

This question already has answers here:
Count Elements SubDocument that match a given criterion
(2 answers)
Closed 5 years ago.
I've the problem with php and MongoDB. Here's my document:
"_id" : ObjectId("58d7815f387e76880c000000"),
"receiver" : "Katty",
"chat" : [
{
"sender" : "jhon",
"date" : ISODate("2017-03-26T08:53:55Z"),
"message" : "Who are you?"
"status" : "sent"
},
{
"sender" : "jhon",
"date" : ISODate("2017-03-26T08:53:55Z"),
"message" : "What do you want?"
"status" : "pending"
}
{
"sender" : "jhon",
"date" : ISODate("2017-03-26T08:53:55Z"),
"message" : "Hah ?"
"status" : "pending"
}
]
And here's my php program:
<?php
$conn = new Mongo();
$db = $conn->selectDB('basarnas');
$query = $db->informasi_bencana;
$nosql = array("_id"=> new MongoId($id), "chat.status"=>"pending");
$result = $query->find($nosql);
$beritasar = $result->count();
$total = $beritasar;
echo "status pending = ".$total;
?>
And the result is
status pending = 1
And I want the result is
status pending = 2
How to count of embedded document when it has status = "pending" ?
You can unwind the embedded document and then match the status then using groupby count all the documents.
db.collection.aggregate([
{ "$unwind": "$chat"},
{$match:{"chat.status": "pending"}},
{ "$group":{"_id":null, count: {$sum:1}}}
])
OR
Simplify fetch all the documents and count the length of the array
db.collection.aggregate([
{ "$unwind": "$chat"},
{$match:{"chat.status": "pending"}},
])

Mongo and Yii -> update with $set a field in all the arrays of a subdocument

I'm having problems updating a specific field in all the arrays of a subdocument. I have the following structure in MongoDB:
{
"_id" : ObjectId("539c9e97cac5852a1b880397"),
"DocumentoDesgloseER" : [
{
"elemento" : "COSTO VENTA",
"id_rubroer" : "11",
"id_documento" : "45087",
"abreviatura" : "CV",
"orden" : "1",
"formula" : "Cuenta Contable",
"tipo_fila" : "1",
"color" : "#FFD2E9",
"sucursal" : "D",
"documentoID" : "0",
"TOTAL" : "55426.62",
},
{ ... MORE OF THE SAME ... }
],
"id_division" : "2",
"id_empresa" : "9",
"id_sucursal" : "37",
"ejercicio" : "2008",
"lastMonthNumber" : NumberLong(6),
}
I need to update the field "documentoID" to a specific value; like "20" for example, in all the arrays of the subdocument "DocumentoDesgloseER". How I can do this?
I tried the following (with $ operator) and is not working:
$querySearch = array('id_division'=>'2', 'id_empresa'=>'9', 'id_sucursal'=>'37', 'ejercicio'=>'2008');
$queryUpdate = array('$set'=>array('DocumentoDesgloseER.$.documentoID'=>'20'));
Yii::app()->edmsMongoCollection('DocumentosDesgloseER')->update($querySearch,$queryUpdate);
By the way, I'm using Yii Framework to make the connection with Mongo. Any help or advice is welcome.
Thanks ;D!
Unfortunately, you can't currently use a positional operator to update all items in an array. There is a ticket opened in the MongoDB JIRA about this issue.
There a two "solutions":
Change your schema so that your embedded documents are in the separate collection (it's probably not what you want).
The best you can do, if you don't want to change your schema, is to update each subdocument in PHP and then save the whole document.

MapReduce for MongoDB on PHP?

I'm new to MongoDB and this is my first use of MapReduce ever.
I have two collections: Shops and Products with the following schema
Products
{'_id', 'type': 'first', 'enabled': 1, 'shop': $SHOP_ID }
{'_id', 'type': 'second', 'enabled': 0, 'shop': $SHOP_ID }
{'_id', 'type': 'second', 'enabled': 1, 'shop': $SHOP_ID }
And
Shops
{'_id', 'name':'L', ... }
{'_id', 'name':'M', ... }
I'm looking for a GROUPBY similar statement for MongoDB with MapReduce to retrieve the Shops with name 'L' that have Products with 'enabled' => 1
How can I do it? Thank you.
It should be possible to retrieve the desired information without a Map Reduce operation.
You could first query the "Products" collection for documents that match {'enabled': 1}, and then take the list of $SHOP_IDs from that query (which I imagine correspond to the _id values in the "Shops" collection), put them in an array, and perform an $in query on the "Shops" collection, combined with the query on "name".
For example, given the two collections:
> db.products.find()
{ "_id" : 1, "type" : "first", "enabled" : 1, "shop" : 3 }
{ "_id" : 2, "type" : "second", "enabled" : 0, "shop" : 4 }
{ "_id" : 3, "type" : "second", "enabled" : 1, "shop" : 5 }
> db.shops.find()
{ "_id" : 3, "name" : "L" }
{ "_id" : 4, "name" : "L" }
{ "_id" : 5, "name" : "M" }
>
First find all of the documents that match {"enabled" : 1}
> db.products.find({"enabled" : 1})
{ "_id" : 1, "type" : "first", "enabled" : 1, "shop" : 3 }
{ "_id" : 3, "type" : "second", "enabled" : 1, "shop" : 5 }
From the above query, generate a list of _ids:
> var c = db.products.find({"enabled" : 1})
> shop_ids = []
[ ]
> c.forEach(function(doc){shop_ids.push(doc.shop)})
> shop_ids
[ 3, 5 ]
Finally, query the shops collection for documents with _id values in the shop_ids array that also match {name:"L"}.
> db.shops.find({_id:{$in:shop_ids}, name:"L"})
{ "_id" : 3, "name" : "L" }
>
Similar questions regarding doing the equivalent of a join operation with Mongo have been asked before. This question provides some links which may provide you with additional guidance:
How to join MongoDB collections in Python?
If you would like to experiment with Map Reduce, here is a link to a blog post from a user who used an incremental Map Reduce operation to combine values from two collections.
http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/
Hopefully the above will allow you to retrieve the desired information from your collections.
Short answer: you can't do that (with a single MapReduce command).
Long answer: MapReduce jobs in MongoDB run only on a single collection and cannot refer other collections in the process. So, JOIN/GROUP BY-like behaviour of SQL is not available here. The new Aggregation Framework also operates on a single collection only.
I propose a two-part solution:
Get all shops with name "L".
Compose and run map-reduce command that will check every product document against this pre-computed list of shops.

MongoDB-PHP: JOIN-like query

Here are the objects:
courses
{ "name" : "Biology", "_id" : ObjectId("4b0552b0f0da7d1eb6f126a1") }
students
{
"name" : "Joe",
"classes" : [
{
"$ref" : "courses",
"$id" : ObjectId("4b0552b0f0da7d1eb6f126a1")
}
],
"_id" : ObjectId("4b0552e4f0da7d1eb6f126a2")
}
Using the PHP Mongo Class, how do I get all the students that has a biology course?
Thanks
You'll need to query twice. I dont have my environment in front of me, but something similar to what's below. I may have the "nested" portion of the second query incorrect.
// First grab the ID for the course.
$course = $collection->findOne(array("name" => "Biology"));
// Next query the students collection.
$collection->find(array("classes" => array("id" => $course['_id'])));

Categories