0

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
1
  • What is the source of your data? In particular, what are the ObjectId(...) items? These make it invalid JSON, and there's not much you can do without sanitising it first. Commented Aug 25, 2018 at 22:54

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

"I fixed up your data to make it JSON but that's not a big deal" I would have thought it was a very big deal, depending on what ObjectId(...) means. I don't think you can just strip those out without confirming with the OP, and even if you do you should be writing code to do it instead of just starting with a fixed version of the input.
The data weren't the important thing. It's getting at all the elements from an array of hashes that's in question. Once anyone knows how to do that, they can adjust that for their situation. Furthermore, it's quite obvious that the data used in the OP code example isn't that data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.