Newbie get _id of returned where query - mongodb

Selecting specific item from returned query (newbie)
Using laravel with the https://github.com/jenssegers/laravel-mongodb#query-builder package so the php is a bit off the norm for MongoDB terminology
I query the database like so:
$role_id = Role::where('name', 'Admin')->get();
How do I access the '_id' of the returned query?
I would like to grab the '_id' in a variable

get() returns Illuminate\Support\Collection object. That means you are getting an array of return items. So, in your case, you should iterate $role_id to loop through the items and get _id. Like this -
foreach ($rid as $role_id) {
echo $rid->_id;
}

Related

mongodb: number of collections in database - native driver

I'm using the mongodb native driver v3.2.3 and trying to query how many collections are in the current database. I thought it would be
db.listCollections()
But this does not appear to return a count.
You can get the collection count of a database via the stats method:
let stats = await db.stats();
console.log(stats.collections);
That function returns a cursor which you can then use 'forEach()' on. Like this:
db.listCollections({}, {nameOnly: true}).forEach((_col) => {
console.log(_col.name)
})
You will then have to increment a counter for each collection, or push each collection name to an array and then check it's length.
Another way to get the collection count quickly would be to use the 'collections()' function like this:
db.collections({}, (error, collections) => {
console.log(collections.length)
})
listCollections source
collections source

MongoDB $push ObjectId

I have tried to do this a number of ways from updateOne, findOneAndUpdate to insert and even tried bulkWrite with no success.
What I have done is I have two collections the users collection and the image_upload collection. I store the users profile image inside image_upload along side all the other images that the user uploads.
What I then store in the users collection is the ObjectID of the image_upload collection that matched the image the user uploaded while creating their account (they can upload a new profile image anytime via edit profile).
So what I would like is the ability to update a ObjectId as I get.
The field personal.profile_id must be an array but is of type objectId in document. Here is the code. I ideally want it to have the ObjectID and not just a string.
$db = static::db()->image_upload;
try {
$newdata = [
"data"=>
[
"url" => $publlic_url,
"type"=> $mimetype,
"date"=>new MongoDB\BSON\UTCDateTime(),
"profile_pic" => true
],
"uid"=>New MongoDB\BSON\ObjectId($uid)
];
$oauth_update = $db->insertOne($newdata);
$view['newdata'] = $newdata;
} catch(MongoResultException $e) {
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->write($e->getDocument());
}
$ids = $oauth_update->getInsertedId();
$latest = $db->findOne(array("uid"=>New MongoDB\BSON\ObjectId($uid)));
// Check first, last and other personal details.
$db = static::db()->users;
try {
$newdata = ['$set' =>["personal.profile_id"=>New MongoDB\BSON\ObjectId($ids)]];
$member_profile = $db->findOneAndUpdate(
['kst'=>New MongoDB\BSON\ObjectId($uid)],
['$push' =>["personal.profile_id"=>['$oid'=>New MongoDB\BSON\ObjectId($ids)]]],
[
'projection' =>
[ 'personal' => 1 ],
"returnDocument" => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER
]);
} catch(MongoResultException $e) {
echo $e->getCode(), " : ", $e->getMessage(), "\n";
var_dump($e->getDocument());
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->write(array('code'=>$e->getCode(), 'message'=>$e->getMessage));
}
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->write(json_encode($member_profile));
There is no work-around for the $push operator requiring an array type. Unfortunately, this is going to require migrating documents in the users collection. Some approaches for doing so are discussed in the following threads:
Converting some fields in Mongo from String to Array
mongodb type change to array
Alternatively, if you'd rather not migrate all documents in users at once, you can have the code execute two findOneAndUpdate() operations in sequence. The first operation could use $type to only match a document with { "personal.profile_id": { $type: "string" }} and then use $set to assign the most recent image ID. A second operation could then match a document with an array type and use the $push strategy (note that $type cannot be used for detecting an array field). The calling code would then expect exactly one of these operations to actually find and update a document (consider logging an error if that is not the case). This approach would then allow you to start collecting old image IDs for migrated documents, but continue overwriting the field for non-migrated documents.
One other observation based on the code you provided:
['$push' =>["personal.profile_id"=>['$oid'=>New MongoDB\BSON\ObjectId($ids)]]]
$oid looks like extended JSON syntax for an ObjectID. That is neither an update operator nor a valid key to use in a BSON document. Attempting to execute this update via the mongo shell yields the following server-side error:
The dollar ($) prefixed field '$oid' 'personal.profile_id..$oid' is not valid for storage."
If you are only looking to push the ObjectID onto the array, the following should be sufficient:
['$push' => ['personal.profile_id' => new MongoDB\BSON\ObjectId($ids)]]

Mongodb find() don't work

Why dosen't db.find work? The console.log gets undefined...
var course = (db.courses.find({ _id: mongo.helper.toObjectID(param.course)}));
console.log(course.body)
The way you are trying use Selects documents in a collection and returns a cursor to the selected documents., so you can't use the way you are trying to use it.
You need to use a callback() to get the records matching the query.
The below code will give result in an array format :-
db.courses.findOne({ _id: mongo.helper.toObjectID(param.course)}).toArray(function(err, result)
{
console.log(result[0]); // will give you the matched record.
})

Referencing property in mongoDB by taking _id

I have a collection which have a document like this:
collection 1
{
_id: ObjectID(),
name: foo
}
I would get ObjectID of the above collection and copy into a document of another collection in order to reference correctly. Should I do simply:
db.collection1.find({name:"foo"},{_id:1})
EDIT
A call to find will return a cursor. Cursors works like an iterator in other languages. You can either attempt to find the first element in the cursor using the next() function and then get it's _id property or simplify your statement using findOne:
var x = db.collection1.findOne({name:"foo"}, {_id:1});
var id = x._id;
This is making an assumption that you are getting a document back from that query. You'll probably want to add a null check on x before grabbing the _id property.

MongoDB: Retrieving the first document in a collection

I'm new to Mongo, and I'm trying to retrieve the first document from a find() query:
> db.scores.save({a: 99});
> var collection = db.scores.find();
[
{ "a" : 99, "_id" : { "$oid" : "51a91ff3cc93742c1607ce28" } }
]
> var document = collection[0];
JS Error: result is undefined
This is a little weird, since a collection looks a lot like an array. I'm aware of retrieving a single document using findOne(), but is it possible to pull one out of a collection?
The find method returns a cursor. This works like an iterator in the result set. If you have too many results and try to display them all in the screen, the shell will display only the first 20 and the cursor will now point to the 20th result of the result set. If you type it the next 20 results will be displayed and so on.
In your example I think that you have hidden from us one line in the shell.
This command
> var collection = db.scores.find();
will just assign the result to the collection variable and will not print anything in the screen. So, that makes me believe that you have also run:
> collection
Now, what is really happening. If you indeed have used the above command to display the content of the collection, then the cursor will have reached the end of the result set (since you have only one document in your collection) and it will automatically close. That's why you get back the error.
There is nothing wrong with your syntax. You can use it any time you want. Just make sure that your cursor is still open and has results. You can use the collection.hasNext() method for that.
Is that the Mongo shell? What version? When I try the commands you type, I don't get any extra output:
MongoDB shell version: 2.4.3
connecting to: test
> db.scores.save({a: 99});
> var collection = db.scores.find();
> var document = collection[0];
In the Mongo shell, find() returns a cursor, not an array. In the docs you can see the methods you can call on a cursor.
findOne() returns a single document and should work for what you're trying to accomplish.
So you can have several options.
Using Java as the language, but one option is to get a db cursor and iterate over the elements that are returned. Or just simply grab the first one and run.
DBCursor cursor = db.getCollection(COLLECTION_NAME).find();
List<DOCUMENT_TYPE> retVal = new ArrayList<DOCUMENT_TYPE>(cursor.count());
while (cursor.hasNext()) {
retVal.add(cursor.next());
}
return retVal;
If you're looking for a particular object within the document, you can write a query and search all the documents for it. You can use the findOne method or simply find and get a list of objects matching your query. See below:
DBObject query = new BasicDBObject();
query.put(SOME_ID, ID);
DBObject result = db.getCollection(COLLECTION_NAME).findOne(query) // for a single object
DBCursor cursor = db.getCollection(COLLECTION_NAME).find(query) // for a cursor of multiple objects