mongodb query find in array - mongodb

I struggle with a find query.
I have two documents in a mongodb grid collection:
{
"_id" : ObjectId("55b8ac2c1a80142e7f7b23cd"),
"metadata" : {
"filename" : "test2.xml",
"contentType" : "application/xml"
},
"data" : {
"type_file" : "test",
"vision_id" : "6987"
},
"filename" : "test2.xml",
"uploadDate" : ISODate("2015-07-29T10:34:20.991Z"),
"length" : NumberLong(9582),
"chunkSize" : NumberLong(261120),
"md5" : "ea40283994f451b357555e53d186ed1e"
}
{
"_id" : ObjectId("55b8ac2c1a80142e7f7b23cd"),
"metadata" : {
"filename" : "test.xml",
"contentType" : "application/xml"
},
"data" : {
"type_file" : "test",
"vision_id" : "1282"
},
"filename" : "test.xml",
"uploadDate" : ISODate("2015-07-29T10:34:20.991Z"),
"length" : NumberLong(9582),
"chunkSize" : NumberLong(261120),
"md5" : "ea40283994f451b357555e53d186ed1e"
}
Now I want to make a query which retreive the document where "filename" = "test.xml" and the tag "vision_id" = "1282".
Now I made the search query like this:
$query =
array('$and' =>
array(
array("filename" => "text.xml),
array("data" => array("vision_id" => "1282")),
),
);
$cursor = $gridFS->find($query)
If I run this I don't get a result:
When I remove the line array("data" => array("vision_id" => "1282")), then I get the last document. (As I predicted).
Could anybody give me a push to the right way, to search also within the data array?
Kind Regards,
Arjan Kroon

I found the solution.
$query =
array('$and' =>
array(
array("filename" => "text.xml"),
array("data.vision_id" => "1282"),
),
);

Related

Add field to every document with existing data (move fields data to new field)

I have almost no experience in SQL or noSQL.
I need to update every document so that my fields "Log*" are under the new field "Log"
I found some help from this StackOverflow, but I am still wondering how to move the data.
Thank you very much
Original document
// collection: Services
{
"_id" : ObjectId("5ccb4f99f4953d4894acbe79"),
"Name" : "WebAPI",
"LogPath" : "Product\\APIService\\",
"LogTypeList" : [
{
"Name" : "ApiComCounter",
"FileName" : "ApiComCounter.log"
},
{
"Name" : "ApiService",
"FileName" : "ApiService.log"
}
]
}
Final Document
// collection: Services
{
"_id" : ObjectId("5ccb6fa2ae8f8a5d7037a5dd"),
"Name" : "InvoicingService",
"Log" : {
"LogPath" : "Product\\APIService\\",
"LogTypeList" : [
{
"Name" : "ApiComCounter",
"FileName" : "ApiComCounter.log"
},
{
"Name" : "ApiService",
"FileName" : "ApiService.log"
}
]
}
}
This requires MongoDB 4.2 or higher:
db.<collection>.updateMany({}, [
{$set: {"Log.LogPath": "$LogPath", "Log.LogTypeList": "$LogTypeList"}},
{$unset: ["LogPath", "LogTypeList"]}
])

MongoDB + Laravel + jenssegers/laravel-mongodb + update nested child elements

Hellow folks, I am new to MongoDB and looking for some answer
Is there any way to update nested array without looping it.
foreach ($post->comments as $key => $comment) {
if ($comment['posted_by'] == $authUser['id']) {
$data = $post->update([
"comments.$key.description" => $dataArray['description'],
"comments.$key.updated_at" => $dataArray['updated_at'],
]);
}}
I want to to do something like below.
$post = Post::where('_id', $id)->where('comments.*.id', $commentId)->update(array('description' => $desc));
Or I have to write raw MongoDB query for that.
I have 1 level nested comment also under main comments so if I want to update nested comment than I have to loop comment array than the nested comment array.
if ($subCommentId) {
foreach ($comment as $nestedkey => $nestedComments) {
if ($nestedComments['id'] === $subCommentId && $nestedComments['posted_by'] == $authUser['id']) {
$data = $post->update([
"comments.$key.$nestedkey.description" => $dataArray['description'],
"comments.$key.$nestedkey.updated_at" => $dataArray['updated_at'],
]);
}
}
}
Something like this :
$post = Post::where('_id', $id)->where('comments.*.id', $commentId)->where('comments.*.*.id', $subCommentId)->update(array('description' => $desc));
Is it good to store comment in the same collection as an array or should I create a new collection for that as maximum BSON document size is 16 megabytes and how much comments it can store like 10K or more?
Below is my sample comment array format under one Collection.
"comments" : [
{
"description" : "description some",
"channel" : "swachhata-citizen-android",
"user_role" : "Citizen",
"id" : "5b4dc367d282f",
"user_role_id" : ObjectId("5accd7f8309a203be03b6441"),
"created_at" : "2018-07-17 15:52:31",
"updated_at" : "2018-07-17 15:52:31",
"ip_address" : "127.0.0.1",
"user_agent" : "PostmanRuntime/6.4.1",
"deleted" : false,
"channel_id" : "5acccfe4309a2038347a5c47",
"posted_by" : NumberInt(1),
"comments" : [
{
"description" : "some description nested",
"channel" : "swachhata-citizen-android",
"user_role" : "Citizen",
"id" : "5b4dcfc7022db",
"user_role_id" : ObjectId("5accd7f8309a203be03b6441"),
"created_at" : "2018-07-17 16:45:19",
"updated_at" : "2018-07-17 16:45:19",
"ip_address" : "127.0.0.1",
"user_agent" : "PostmanRuntime/6.4.1",
"deleted" : false,
"channel_id" : "5acccfe4309a2038347a5c47",
"posted_by" : NumberInt(1)
}
]
}
]
Thanks. :)
To update nested document, you should use arrayFilters:
Post::raw()->updateMany(
[],
[ '$set' => ["comments.$[i].comments.$[j].description" => $desc] ],
[ '$arrayFilters' => [
[
[ "i.id" => "5b4dc367d282f" ],
[ "j.id" => "5b4dcfc7022db" ]
]
]
]
)
Hope it helps :)

How to achieve the following using MongoDB

I used switch statement to assign some text based on different value ; here it returns correct output.
Now from the above output ,again I need to filter out few documents using regular expression.
Some thing like "where status likes 'open%'"
db.accountMailLog.aggregate([
{$match:{'$and': [{recipientId: "3003590"}, {recipientType: "2"}
]}},
{$project :
{
'_id' : 0,
'logCreated' : '$eventOccurredTime',
'subject' : 1,
'resourceType' : 'email',
'campaignName' : 1,
'emailSendDay' : 1,
'logDate' : '$eventOccurredTime',
'sentMethod' : 'campaign-email',
'visitorKey' : '',
'mediaHash' : '',
"status" : {'$switch' :
{'branches' :
[
{'case' : {'$eq' : ['$status','1']},'then' : "delivered"},
{'case' : {'$eq' : ['$status','2']},'then' : "opened"},
{'case' : {'$eq' : ['$status','3']},'then' : "clicked"},
{'case' : {'$eq' : ['$status','4']},'then' : "bounced"},
{'case' : {'$eq' : ['$status','5']},'then' : "unsubscribed"},
{'case' : {'$eq' : ['$status','6']},'then' : "complained"}
]
}
}
}},
]);
Thanks !!!
You can use Regexp. Something like:
"status": open/

Mongoid query embedded document and return parent

I have this document, each is a tool:
{
"_id" : ObjectId("54da43aea96ddcc40915a457"),
"checked_in" : false,
"barcode" : "PXJ-234234",
"calibrations" : [
{
"_id" : ObjectId("54da46ec546173129d810100"),
"cal_date" : null,
"cal_date_due" : ISODate("2014-08-06T00:00:00.000+0000"),
"time_in" : ISODate("2015-02-10T17:46:20.250+0000"),
"time_out" : ISODate("2015-02-10T17:46:20.250+0000"),
"updated_at" : ISODate("2015-02-10T17:59:08.796+0000"),
"created_at" : ISODate("2015-02-10T17:59:08.796+0000")
},
{
"_id" : ObjectId("5509e815686d610b70010000"),
"cal_date_due" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_in" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_out" : ISODate("2015-03-18T21:03:17.959+0000"),
"cal_date" : ISODate("2015-03-18T21:03:17.959+0000"),
"updated_at" : ISODate("2015-03-18T21:03:17.961+0000"),
"created_at" : ISODate("2015-03-18T21:03:17.961+0000")
},
{
"_id" : ObjectId("5509e837686d610b70020000"),
"cal_date_due" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_in" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_out" : ISODate("2015-03-18T21:03:51.189+0000"),
"cal_date" : ISODate("2015-03-18T21:03:51.189+0000"),
"updated_at" : ISODate("2015-03-18T21:03:51.191+0000"),
"created_at" : ISODate("2015-03-18T21:03:51.191+0000")
}
],
"group" : "Engine",
"location" : "Here or there",
"model" : "ZX101C",
"serial" : NumberInt(15449),
"tool" : "octane analyzer",
"updated_at" : ISODate("2015-09-30T20:43:55.652+0000"),
"description" : "Description...",
}
Tools are calibrated periodically. What I want to do is grab tools that are due this month.
Currently, my query is this:
scope :upcoming, -> { where(:at_ats => false).where('calibrations.0.cal_date_due' => {'$gte' => Time.now-1.day, '$lte' => Time.now+30.days}).order_by(:'calibrations.cal_date_due'.asc) }
However, this query gets the tool by the first calibration object and it needs to be the last. I've tried a myriad of things, but I'm stuck here.
How can I make sure I'm querying the most recent calibration document, not the first (which would be the oldest and therefore not relevant)?
You should look into aggregation framework and $unwind operator.
This link may be of help.
This link may be helpful. It contains an example of use of 'aggregation framework' for get the last element of the array, that is, the most recent in your case.

What is the correct query for a Doctrine ODM Geospatial query?

I've set up a classes as described at
http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/reference/geospatial-queries.html
My 2d index is set correctly in mongo
> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "pfcd_dev.media", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "pfcd_dev.events", "name" : "_id_" }
{ "v" : 1, "key" : { "coordinates" : "2d" }, "ns" : "pfcd_dev.events", "name" : "coordinates_" }
When I run the following command on the mongo shell, I get numerous results returned.
db.runCommand( { geoNear : "events" , near : [50,60], num : 10 } )
I've tried all the following variations for near(), all return zero results
$places = $this->dm->createQueryBuilder('\Application\Event')->field('coordinates')->near('[50,60]')->getQuery()->execute();
$places = $this->dm->createQueryBuilder('\Application\Event')->field('coordinates')->near('50,60')->getQuery()->execute();
$places = $this->dm->createQueryBuilder('\Application\Event')->field('coordinates')->near(50,60)->getQuery()->execute();
$places = $this->dm->createQueryBuilder('\Application\Event')->field('coordinates')->near(array(50,60))->getQuery()->execute();
The documentation on Doctrine's site seems to be a bit off. Just for record, I've created a gist showing my classes (trucated). https://gist.github.com/1627491
This is the output of debug()
$this->dm->createQueryBuilder('\Application\Event')->field('coordinates')->near('50,60')->debug();
Array
(
[type] => 10
[mapReduce] => Array
(
[map] =>
[reduce] =>
[options] => Array
(
)
)
[near] => Array
(
[coordinates] => 50,60
)
)
Have you tried getting rid of your extends Base for your models?
You also might try something like:
$places = $this->dm->createQueryBuilder('\Application\Event')->field('coordinates.latitude')->near(50)->field('coordinates.longitude')->near(60)->getQuery()->execute();