Mongodb & Symfony QueryBuilder - mongodb

Does someone know where I can find some informations about Mongodb QueryBuilder in Symfony2 please? Maybe some examples or some tutorials.
I googled the question but didn't find something good enough..
More specifically I want to retrieve a field in a document based on the embedded document.
Here is an example of document :
{
"name":"Foo",
"age":"25",
"gender":"Male",
"products":[
{
"name":"Apple",
"price":"12.00",
"date":"2015-12-02"
},
{
"name":"Banana",
"price":"9.00",
"date":"201-11-31"
},
]
}
And I want to retrieve the name "Foo" based on the date in products array.
At the moment I use distinct() to list all fields in products.

Simple doctrine mongodb example for EmbedMany in symfony
Assume that a League may have one or many Teams so it is a Embed Many like in your case. Full example is above. If you want more info then I think first 5 posts are enough for you.
EXAMPLE USAGE
->findOneByProperty('name', 'Premiership')
REPO
use Doctrine\ODM\MongoDB\DocumentRepository;
class LeagueRepository extends DocumentRepository
{
/**
* #param string $field
* #param string $data
*
* #return array|null|object
*/
public function findOneByProperty($field, $data)
{
return
$this->createQueryBuilder('League')
->field($field)->equals($data)
->getQuery()
->getSingleResult();
}
}
DUMMY DATA
db.getCollection('league').find({})
/* 1 */
{
"_id" : ObjectId("564fa07add576ebcf90041ac"),
"name" : "Super Lig",
"createdAt" : ISODate("2015-11-20T22:36:42.000Z")
}
/* 2 */
{
"_id" : ObjectId("564fa081dd576ebbf90041ad"),
"name" : "Premiership",
"createdAt" : ISODate("2015-11-20T22:36:49.000Z"),
"updatedAt" : ISODate("2015-11-20T22:37:33.000Z"),
"teams" : [
{
"_id" : ObjectId("564fa0a6dd576ef2f80041ad"),
"name" : "Arsenal",
"createdAt" : ISODate("2015-11-20T22:37:26.000Z")
},
{
"_id" : ObjectId("564fa0addd576ebaf90041ad"),
"name" : "Liverpool",
"createdAt" : ISODate("2015-11-20T22:37:33.000Z")
}
]
}

Related

Morphia: How to i match a 2 level nested document in mongodb?

I have a collection in which documents look like this:
/* 1 */
{
"_id" : "U1234",
"person" : {
"address" : {
"city" : "X"
}
}
}
/* 2 */
{
"_id" : "U1235",
"person" : {
"address" : {
"city" : "Y"
}
}
}
The below raw shell query works fine, but cannot convert it to morphia code:
db.getCollection('bypass').aggregate([
{$match:{"person.address.city": "X"}}
])
How do I write a morphia aggregate query to count the cities with X value assuming that I have an index on city field?
I tried
query.field("person.address.city", "X");
OR
AggregationPipeline aggregationPipeline = datastore.createAggregation(Session.class)
.project(Projection.projection("cityFound", "person.address.city"))
.match(query.field("cityFound").equal("X"));
Unfortunately, both doesn't work. What am I doing wrong here? I am using Morphia v1.2.1

add field to document mongodb keeping previous data

I'm trying to add a new field to a document
/* 1 */
{
"_id" : ObjectId("5d3b1d8c708bf66fc760afb6"),
"user" : "myuser",
"password" : "$2y$10$Oh.RKbvf4eT5gozLnD7A0uS5C/k6YluYw0k7uShPD2Elu6FKNBQn2"
}
/* 2 */
{
"_id" : ObjectId("5d3c4e70faa55a342c08c40a"),
"user" : "user2",
"pass" : "$2y$10$Oh.RKbvf4eT5gozLnD7A0uS5C/k6YluYw0k7uShPD2Elu6FKNBQn2"
}
with the comand
db.users.update({"user":"user2"},{"widgets":1})
But then the document that matches previous info is lost
/* 2 */
{
"_id" : ObjectId("5d3c4e70faa55a342c08c40a"),
"widgets" : 1.0
}
How can I update keeping the preious data of the document?
You are missing $set here. If you donot provide $set then all the fields will be replaced with the provided one in your case user and pass is replaced with widgets. As mention in docs
db.users.update({"user":"user2"},{$set: {"widgets":1}})

Make nested queries in MongoDB 3.0.7

I have sub-events belonging to events belonging to an user, and I know the user's username - how do I get a list of the sub-events?
Is this going in the right direction? Or is it completely off?
db.subevents.find({_id: {$in:
db.events.find({_id: {$in:
db.users.find({"username":"userx"},{_id:1})}},{_id:1})}})
Edit: Here is a sample of the data structure:
/* Event */
{
"_id" : "XjhAqqNBkezKY3mdN",
"name" : "My event",
"userId" : "FiKsAAAgBb7cNoPH7"
}
/* Subevent */
{
"_id" : "WkYAqBXNpJryp7rum",
"name" : "The subevent",
"eventId" : "hQXNzX3jbWppbAYFH"
}
/* User */
{
"_id" : "RTHh5srhLMQp625zF",
"username" : "userx"
}
Following profesor79's advice to use three different calls, I put together this solution to get all the sub-events belonging to the user:
var userIds = db.users.find({"username":"userx"}).map(function(user) {
return user._id;
});
var eventIds= db.events.find({userId: {$in:userIds}}).map(function(event) {
return event._id;
});
db.subevents.find({eventId:{$in:eventIds}});
The only way is to make 3 ddifrent calls in mongo 3.0.7
GetUSerData
GetEventData
GetSubEventData
As you have relational schema here - this should be easy.
You could improve schema and remove subEvent collection by embedding subEvents documents into one events document
EDIT
/* Event */
{
"_id" : "XjhAqqNBkezKY3mdN",
"name" : "My event",
"userId" : "FiKsAAAgBb7cNoPH7"
"subewents" : [{
"_id" : "WkYAqBXNpJryp7rum",
"name" : "The subevent",
"eventId" : "hQXNzX3jbWppbAYFH"
}, {
"_id" : "WkYAqBXNpJryp7rum2",
"name" : "The subevent2",
"eventId" : "hQXNzX3jbWppbAYFH"
}, {
"_id" : "WkYAqBXNpJryp7rum",
"name" : "The subevent",
"eventId" : "hQXNzX3jbWppbAYFH"
}
]
}
/* User */
{
"_id" : "RTHh5srhLMQp625zF",
"username" : "userx"
}

Get specific object in array of array in MongoDB

I need get a specific object in array of array in MongoDB.
I need get only the task object = [_id = ObjectId("543429a2cb38b1d83c3ff2c2")].
My document (projects):
{
"_id" : ObjectId("543428c2cb38b1d83c3ff2bd"),
"name" : "new project",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b"),
"members" : [
ObjectId("5424ac37eb0ea85d4c921f8b")
],
"US" : [
{
"_id" : ObjectId("5434297fcb38b1d83c3ff2c0"),
"name" : "Test Story",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b"),
"tasks" : [
{
"_id" : ObjectId("54342987cb38b1d83c3ff2c1"),
"name" : "teste3",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
},
{
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
]
}
]
}
Result expected:
{
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
But i not getting it.
I still testing with no success:
db.projects.find({
"US.tasks._id" : ObjectId("543429a2cb38b1d83c3ff2c2")
}, { "US.tasks.$" : 1 })
I tryed with $elemMatch too, but return nothing.
db.projects.find({
"US" : {
"tasks" : {
$elemMatch : {
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2")
}
}
}
})
Can i get ONLY my result expected using find()? If not, what and how use?
Thanks!
You will need an aggregation for that:
db.projects.aggregate([{$unwind:"$US"},
{$unwind:"$US.tasks"},
{$match:{"US.tasks._id":ObjectId("543429a2cb38b1d83c3ff2c2")}},
{$project:{_id:0,"task":"$US.tasks"}}])
should return
{ task : {
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
Explanation:
$unwind creates a new (virtual) document for each array element
$match is the query part of your find
$project is similar as to project part in find i.e. it specifies the fields you want to get in the results
You might want to add a second $match before the $unwind if you know the document you are searching (look at performance metrics).
Edit: added a second $unwind since US is an array.
Don't know what you are doing (so realy can't tell and just sugesting) but you might want to examine if your schema (and mongodb) is ideal for your task because the document looks just like denormalized relational data probably a relational database would be better for you.

mongodb retrieving array values from a find query

Here's my mongodb document:
{ "FRIENDS" : [
{ "LOC" : "13.039064033333332,77.5547927", "NAME" : "A1", "PHONE_NUMBER" : "817361155" } ],
"MYID" : "349512956",
"MYLOCATION" : "13.0389541,77.5549799",
"OCCASION" : "cafe",
"_id" : ObjectId("503d87150f43159357000001"),
"average" : "13.0389541,77.5549799" }
Here's my query
> db.test_collection.find({"MYID":"349512956"},{"FRIENDS.PHONE_NUMBER":"817361155"});
and the output
{ "FRIENDS" : [ { "PHONE_NUMBER" : "817361155" } ], "_id" : ObjectId("503d87150f43159357000001") }
However, I want the entire friend document included in the result. LOC, NAME, PHONE_NUMBER. How do I get these ? Any help will be greatly appreciated. I'm searching through the monogo docs but am unable to find my answer.
Try this
// i.e., select * from things where MYID=somethig and PHONE_NUMBER="foo"
db.test_collection.find({"MYID":"349512956", "FRIENDS.PHONE_NUMBER":"817361155"});
To be more specific, the second argument selects the fields that you want outputted. See the actual implementation below:
> db.test_collection.find
function (query, fields, limit, skip, batchSize, options) {
return new DBQuery(this._mongo, this._db, this, this._fullName,
this._massageObject(query), fields, limit, skip, batchSize, options ||
this.getQueryOptions());
}