Perl get array element from mongodb - mongodb

I wanted to fetch array element and store in Perl variable. If I put 0 in replace of ? in $cur->{Type}[?]->{_id} I'm able to get only one array element but I want all. below is my collection
{
"_id" : ObjectId("5b7fdb050cc3c23478005741"),
"DBName" : "sample",
"DBServerURL" : "mongodb://localhost:27017/",
"Type" : [
{
"_id" : ObjectId("5b801dc963f8c81df83891bd")
},
{
"_id" : ObjectId("5b801dc963f8c81df83891be")
},
{
"_id" : ObjectId("5b801dc963f8c81df83891bf")
},
{
"_id" : ObjectId("5b801dc963f8c81df83891c0")
}
]
}
I'm trying to get ObjectId from all fields
$cursor = $CustColl->find(
{DBName => "sample",DBServerURL => "mongodb://localhost:27017/"},{'_id' => 1, 'Type.$._id' => 1, 'DBServerURL' => 1, 'DBName' => 1}
);
while(my $cur = $cursor->next){
my $cid = "$cur->{_id}" ;
my $jid = "$cur->{Type}[?]->{_id}" ;
my $url = "$cur->{DBServerURL}" ;
my $name = "$cur->{DBName}" ;
print "$cid : $jid : $url : $name\n" ;
}
I wanted an output like below:
5b7fdb050cc3c23478005741 : 5b801dc963f8c81df83891bd : mongodb://localhost:27017/ sample
5b7fdb050cc3c23478005741 : 5b801dc963f8c81df83891be : mongodb://localhost:27017/ sample
5b7fdb050cc3c23478005741 : 5b801dc963f8c81df83891bf : mongodb://localhost:27017/ sample
5b7fdb050cc3c23478005741 : 5b801dc963f8c81df83891c0 : mongodb://localhost:27017/ sample

You are almost there. First, I fixed up your data to make it JSON but that's not a big deal:
my $json = q([{
"_id" : "5b7fdb050cc3c23478005741",
"DBName" : "sample",
"DBServerURL" : "mongodb://localhost:27017/",
"Type" : [
{
"_id" : "5b801dc963f8c81df83891bd"
},
{
"_id" : "5b801dc963f8c81df83891be"
},
{
"_id" : "5b801dc963f8c81df83891bf"
},
{
"_id" : "5b801dc963f8c81df83891c0"
}
]
} ]);
use JSON::XS;
my $perl = decode_json( $json );
That's a JSON array so you can go through it one element at a time. In Perl that shows up as an array reference Using the postfix dereference introduced in v5.20 makes this palatable (but not so hard without it):
while(my $cur = shift $perl->#*){ # or #$perl
my $cid = $cur->{_id} ;
my $url = $cur->{DBServerURL} ;
my $name = $cur->{DBName} ;
foreach my $hash ( $cur->{Type}->#* ) { # or #{ $cur->{Type} }
my $jid = $hash->{_id};
print "$cid : $jid : $url : $name\n" ;
}
}
The trick is that the $jid stuff is in another array and you want to go through those individually. There's a foreach inside the while to do that. It runs once for each of those and outputs the lines.

Related

mongodb query find in array

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"),
),
);

Perl Newbie - Printing value from array

I am brand new to perl. I am trying to grab a string out of some JSON output. My code below works, but seems like there is a smarter way to do this. Here is a sample of the JSON
$VAR1 = '{
"hasDetailRows" : true,
"reportMetadata" : {
"reportFormat" : "TABULAR",
"detailColumns" : [ "SUBJECT", "COMMENT_CREATED_DATE", "CASE_COMMENT_CREATED_BY" ],
"reportBooleanFilter" : null,
"reportFilters" : [ {
"column" : "CASE_COMMENT_CREATED_BY",
"operator" : "equals",
"value" : "Username"
} ],
"aggregates" : [ "RowCount" ],
"groupingsDown" : [ ],
"groupingsAcross" : [ ],
"developerName" : "My_Comments",
"reportType" : {
"type" : "CaseList",
"label" : "Cases"
},
"name" : "My Comments",
"id" : "REDCATED",
"currency" : null
},
"factMap" : {
"T!T" : {
"rows" : [ {
"dataCells" : [ {
"value" : "ID",
"label" : "Description"
}, {
"value" : "2014-02-17T22:01:17Z",
"label" : "2/17/2014 4:01 PM"
}, {
"value" : "USER ID",
"label" : "User Name"
} ]
}`
What I need is that label with the timestamp.
And here is my code
#!/usr/bin/perl
use warnings;
use strict;
use WWW::Mechanize;
use WWW::Salesforce;
use Data::Dumper;
use JSON -support_by_pp;
use 5.010;
use Date::Parse;
my $mech = WWW::Mechanize->new();
$mech->agent('Mozilla/5.0');
# Authenticate first via SOAP interface to get a session ID:
my $sforce = eval { WWW::Salesforce->login(
username => 'REDACTED',
password => 'REDACTED' ); };
die "Could not login to SFDC: $#" if $#;
# Get the session ID:
my $hdr = $sforce->get_session_header();
my $sid = ${$hdr->{_value}->[0]}->{_value}->[0];
#Our request
$mech->add_header( "Authorization" => "OAuth $sid" );
$mech->add_header( "X-PrettyPrint" => '1' );
$mech->get("SOME URL THAT RETURNS JSON");
my $content = $mech->content;
my $json = new JSON;
my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($content);
Here is what I have currently that grabs the value that I want from $content. All I need is the first result which is why I am killing the loop after the first run. Everytime I have tried this without a loop I get "Not a HASH reference". So all I need to know is the correct syntax for printing out the value of $timestamp.
foreach my $field(#{$json_text->{factMap}->{'T!T'}->{rows}}){
my $now = time();
my $timestamp = str2time($field->{dataCells}[1]->{'label'});
my $diff = int (($now - $timestamp)/60);
my $current = getLoggingTime();
print $current . " \t";
say "Time since last activity: " . $diff . " minutes!" ;
last;
}
sub getLoggingTime {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $nice_timestamp = sprintf ( "%04d-%02d-%02d %02d:%02d:%02d",
$year+1900,$mon+1,$mday,$hour,$min,$sec);
return $nice_timestamp;
}
I don't know what your without-a-loop version looks like, but this should work:
my $timestamp = str2time(
$json_text->{factMap}{'T!T'}{rows}[0]{dataCells}[1]{label}
);
Currently, you're looping over the elements of the array referenced by
$json_text->{factMap}{'T!T'}{rows}
...and stopping at the first entry
$json_text->{factMap}{'T!T'}{rows}[0]
...and dereferencing that to get to
$json_text->{factMap}{'T!T'}{rows}[0]{dataCells}[1]{label}

Is it possible to query MongoDB, using ONLY Array([x][y[x][z]]) Approach? NOT knowing Elements' Content?

This is the first of 7 test/example documents, in collection "SoManySins."
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Treats" : "Sin1 = Gluttony",
"Sin1" : "Gluttony",
"Favourited" : "YES",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
I would like to be able to query to retrieve any info in any position,
just by referring to the position. The following document,
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Sin1" : "Gluttony",
"?????????" : "??????",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
One could retrieve whatever might be in the 3rd key~value
pair. Why should one have to know ahead of time what the
data is, in the key? If one has the same structure for the
collection, who needs to know? This way, you can get
double the efficiency? Like having a whole lot of mailboxes,
and your app's users supply the key and the value; your app
just queries the dbs' documents' arrays' positions.
Clara? finally? I hope?
The sample document you've provided is not saved as an array in BSON:
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Sin1" : "Gluttony",
"?????????" : "??????",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
Depending on the MongoDB driver you are using, the fields here are typically represented in your application code as an associative array or hash. These data structures are not order-preserving so you cannot assume that the 3rd field in a given document will correspond to the same field in another document (or even that the same field ordering will be consistent on multiple fetches). You need to reference the field by name.
If you instead use an array for your fields, you can refer by position or select a subset of the array using the $slice projection.
Example document with an array of fields:
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"fields": [
{ "Sin1" : "Gluttony" },
{ "?????????" : "??????" },
{ "RecentActivity" : "YES" },
{ "GoAgain?" : "YeaSure." }
]
}
.. and query to find the second element of the fields array (a $slice with skip 1, limit 1):
db.SoManySins.find({}, { fields: { $slice: [1,1]} })
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"fields" : [
{
"?????????" : "??????"
}
]
}
This is one way to Query and get back data when you may not
know what the data is, but you know the structure of the data:
examples in Mongo Shell, and in PHP
// the basics, setup:
$dbhost = 'localhost'; $dbname = 'test';
$m = new Mongo("mongodb://$dbhost");
$db = $m->$dbname;
$CursorFerWrites = $db->NEWthang;
// defining a set of data, creating a document with PHP:
$TheFieldGenerator = array( 'FieldxExp' => array(
array('Doc1 K1'=>'Val A1','Doc1 K2'=>'ValA2','Doc1 K3'=>'Val A3'),
array('Doc2 K1'=>'V1','Doc2 K2'=>'V2','Doc2 K3'=>'V3' ) ) ) ;
// then write it to MongoDB:
$CursorFerWrites->save($TheFieldGenerator);
NOTE : In the Shell : This produces the same Document:
> db.NEWthang.insert({"FieldxExp" : [
{"Doc1 K1":"Val A1","Doc1 K2":"Val A2","Doc1 K3":"Val A3"},
{"Doc2 K1":"V1", "Doc2 K2":"V2","Doc2 K3":"V3"}
]
})
#
Now, some mongodb Shell syntax:
> db.NEWthang.find().pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc1 K1" : "Val A1",
"Doc1 K2" : "Val A2",
"Doc1 K3" : "Val A3"
},
{
"Doc2 K1" : "V1",
"Doc2 K2" : "V2",
"Doc2 K3" : "V3"
}
]
}
> db.NEWthang.find({}, { "FieldxExp" : { $slice: [1,1]} } ).pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc2 K1" : "V1",
"Doc2 K2" : "V2",
"Doc2 K3" : "V3"
}
]
}
> db.NEWthang.find({}, { "FieldxExp" : { $slice: [0,1]} } ).pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc1 K1" : "Val A1",
"Doc1 K2" : "Val A2",
"Doc1 K3" : "Val A3"
}
]
}
Finally, how about write the Query in some PHP ::
// these will be for building the MongoCursor:
$myEmptyArray = array();
$TheProjectionCriteria = array('FieldxExp'=> array('$slice' => array(1,1)));
// which gets set up here:
$CursorNEWthang1 = new MongoCollection($db, 'NEWthang');
// and now ready to make the Query/read:
$ReadomgomgPls=$CursorNEWthang1->find($myEmptyArray,$TheProjectionCriteria);
and the second document will be printed out:
foreach ($ReadomgomgPls as $somekey=>$AxMongoDBxDocFromCollection) {
var_dump($AxMongoDBxDocFromCollection);echo '<br />';
}
Hope this is helpful for a few folks.

Perl and MongoDB: Inserting Array of Objects into Key-Value Pairs

I'd like to insert into my MongoDB using perl the following BSON structure:
{"name" : "BOB", "stuff" : [{"area1": [1,2,3,4,5]}, {"area2": [5,6,7,8,9]}]}
But have had a hard time finding a good example of this. I tried the following:
#!/usr/bin/perl
use MongoDB;
use MongoDB::Database;
use MongoDB::OID;
my $conn = MongoDB::Connection->new;
my $db = $conn->test;
my $users = $db->real_time10;
$users->insert
({
"name" => "BOB",
"stuff" =>
"area1" => [1,2,3,4,5],
"area2" => [5,6,7,8,9]
});
Which grossly outputs upon query in the mongo shell:
db.real_time10.find()
{ "_id" : ObjectId("4fc912fa000207ec08000000"), "ARRAY(0xa5bdd4)" : "area2", "A
RAY(0x2f2e844)" : null, "name" : "BOB", "stuff" : "area1" }
What is going on? Is there a simple way to do this?
My dream/desired output would be:
> db.real_time10.find()
{ "_id" : ObjectId("4fc912fa000207ec08000000"), "stuff" : {"area1" : [1,2,3,4,5],
"area2": [5,6,7,8,9]}, "name" : "BOB" }
Your missing your anonymous-array-constructor (square-brackets) in your example code - but including them in your BSON example. To get your desired output try:
$users->insert({
"name" => "BOB",
"stuff" => {
"area1" => [1,2,3,4,5],
"area2" => [5,6,7,8,9]
}
});
By excluding the array constructor it builds up a hash with the supplied array key, value pairs so it would be parsed as the following (which matches your data-dump):
{
"name" => "BOB",
"stuff" => "area1",
[1,2,3,4,5] => "area2",
[5,6,7,8,9] => undef
}
Note: an array-ref in scalar context will be seen as a string like "ARRAY(0x6052b8)"
Ah, it's this:
#!/usr/bin/perl
use MongoDB;
use MongoDB::Database;
use MongoDB::OID;
my $conn = MongoDB::Connection->new;
my $db = $conn->test;
my $users = $db->real_time10;
$users->insert({
"name" => "BOB",
"stuff" =>
{"area1" => [1,2,3,4,5],
"area2" => [5,6,7,8,9]}
});
This outputs:
{ "_id" : ObjectId("4fc91f110064e9d40b000000"), "name" : "BOB", "stuff" : { "are
a2" : [ 5, 6, 7, 8, 9 ], "area1" : [ 1, 2, 3, 4, 5 ] } }

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();