I am using MongoDB native driver for NodeJS, and am having trouble converting ObjectID to a string.
My code looks like:
db.collection('user', function(err, collection) {
collection.insert(data, {safe:true}, function(err, result) {
var myid = result._id.toString();
console.log(myid);
)};
});
I have tried various suggestions on StackOverflow like:
myid = result._id.toString();
myid = result._id.toHexString();
but none of them seemed to work.
I am trying to convert the ObjectID to base64 encoding.
Not sure if I am running into supported functionality under the Mongo native driver.
This work for me:
var ObjectID = require('mongodb').ObjectID;
var idString = '4e4e1638c85e808431000003';
var idObj = new ObjectID(idString);
console.log(idObj);
console.log(idObj.toString());
console.log(idObj.toHexString());
Output:
4e4e1638c85e808431000003
4e4e1638c85e808431000003
4e4e1638c85e808431000003
insert returns an array of results (as you can also send an array of objects to be inserted), so your code is trying to get the _id from the array instance rather than the first result:
MongoClient.connect("mongodb://localhost:27017/testdb", function(err, db) {
db.collection("user").insert({name:'wiredprairie'}, function(err, result) {
if (result && result.length > 0) {
var myid = result[0]._id.toString();
console.log(myid);
}
});
});
Also, you won't need to base64 encode the result of calling toString on an ObjectId as it's returned as a hex number already. You could also call: result[0]._id.toHexString() to get the Hex value directly (toString just wraps toHexString).
Related
Im doing a RESTful server on NodeJS and MongoDB but im stuck on the DELETE method, because im getting the error
"Argument passed in must be a single String of …modules\express\lib\router\index.js:174:3"
when trying to cast the req.body.listId into an ObjectId.
Here's my code:
router.delete('/', function(req, res){
var db = req.db;
var collection = db.get('listcollection');
var oId = new ObjectId(req.body.listId); //The exception is here
collection.remove(
{
"_id": oId
},function(err,doc){
if (err) {
res.json("There was a problem deleting the information to the database.");
}
else {
res.json("Successfully deleted");
}
}
);
});
Solved!:
The listId parameter was quoted ("58f8b2cc8cf726ca76551589") so I did an slice. Anyway I changed the param to be received in the URL, here's the code: Thanks!!
router.delete('/:listId', function(req, res){
var db = req.db;
var collection = db.get('listcollection');
var listId = req.params.listId;
listId = listId.slice(1, listId.length - 1);
var oId = new ObjectId(listId);
collection.remove(
{
"_id": oId
},function(err,doc){
if (err) {
res.json("There was a problem deleting the information to the database.");
}
else {
res.json("Successfully deleted");
}
}
);
});
The error happens because req.body.listId does not follow the rule of ObjectId -- ObjectId is a string of 12 bytes (24 0-9 or a-f characters, e.g. "507f1f77bcf86cd799439011"). What may go wrong is:
req.body.listId is a plain number, not a String type, e.g. 89876.
req.body.listId is a String, but not follow the rule described above.
Although it is not RESTful, HTTP DELETE request with JSON body is totally OK. The Node.js server can receive the request and its body.
I have created a little application that implemented a JSON file as the data store. I'm trying to learn about MEAN, so I'm trying to convert it to a NODE.js app.
I have created a mongoDB importing my JSON file using mongoimport. The db is there and connected. When I put http://localhost:3000/api/characters into the browser it returns JSON for all the characters.
I have built a connection string and required it into my controller as follows...
// FROM node app characters.controller.js
var dbconn = require('../data/dbconnection.js');
var characterData = require('../data/characters.json');
module.exports.charactersGetAll = function(req, res) {
var db = dbconn.get();
var collection = db.collection('characters');
// Get the documents from the collection
// Need to use to Array() as its only a cursor if you don't
collection
.find()
.toArray(function(err, docs) {
console.log("Found characters!", docs);
res
.status(200)
.json(docs);
});
//console.log('db', db);
//console.log("GET the Characters");
//console.log(req.query);
res
.status(200)
.json(characterData);
};
module.exports.charactersGetOne = function(req, res) {
var charId = req.params.id;
var thisChar = characterData[charId];
console.log("GET characterId", charId);
res
.status(200)
.json(thisChar);
};
From the non-NODE version of the app, I call in the JSON data as follows in my main.js file:
//FROM TRADITIONAL HTML/JS application
// Get JSON and callback so JSON can be stored globally
$.getJSON('people.json', callback);
// Populate faces and names in HTML
function callback(data) {
/*optional stuff to do after success */
var $charNames = $('.char-names');
var $faceImage = $('.faces');
$.each(data, function(index, val) {
console.log("success");
/* iterate through array or object */
/* .eq() method constructs new object from one element from set */
$charNames.eq(index).text(val.name);
$faceImage.eq(index).attr('src', val.image);
//Push all JSON to array
allTheCharacters.push(val);
allTheCharactersComp.push(val);
});
}
What I want to ask is – Is there a simple way I can access the mongoDB in the non-NODE main.js file instead of using the $.getJSON method and how would I add/adapt this for the node characters.controller.js
Hopefully, I am making sense. Apologies in advance for any misunderstanding.
I am new to streams and I am trying to fetch the data from my collection using reactive-superglue/highland.js (https://github.com/santillaner/reactive-superglue).
var sg = require("reactive-superglue")
var query = sg.mongodb("mongodb://localhost:27017/qatrackerdb").collection("test1")
exports.findAll = function (err, res) {
query.find()
.map(JSON.stringify)
.done(function(data) {
console.log(data)
res.end(data)
})
}
my curl request:
curl -i -X GET http://localhost:3000/queries/
Your code snippet does not work because highland.js's .done() does not return the result. You should either use Stream.each to iterate each element or Stream.toArray to get them all as an array.
BTW, I'm reactive-superglue's author. reactive-superglue is my (work-in-progress) take on real-world usage of highland's streams, built on top of highland.js
Cheers!
I'm not really sure what reactive-superglue is doing for you here. It looks like it's just a compilation of highland shortcuts for getting different data sources to respond.
You can use highland to do this directly like this:
var collection = sg.mongodb("mongodb://localhost:27017/qatrackerdb").collection("test1");
return h( collection.find({}) )
.map(h.extend({foo: "bar"})
.pipe(res);
Edit:
The above snippet still uses reactive-superglue, but you could just use the node mongo driver:
var url = 'mongodb://localhost:27017/qatrackerdb';
MongoClient.connect(url, function(err, db) {
h( db.collection("test1").find({}) )
.map(h.extend({foo: "bar"})
.pipe(res);
});
I was able to retrieve the payload using this approach, not sure if this is the best way, would greatly appreciate any other suggestions or explanations.
exports.findAll = function (err, res) {
query.find()
.map(JSON.stringify)
.toArray(function(x){
res.end(x + '')
})
}
I have a JSON Object called parsedSong that I want to convert into a Mongo document using Mongoose.
var newSong = new Song(parsedSong);
However, this only provides me with a new document that only has an id attribute. How can I make a conversion that doesn't cut my data from parsedSong?
I assumed you have defined these variables in schema. Then you can make something like this:
var bestSong = {
artist: "Seether",
song: "Careless Whisper"
};
var song = new Song(bestSong);
song.save(function(err) {
if(err) throw err;
console.log('saved');
});
And now this song should be in database.
I'm new to mongo and node and i'm trying to create a script that essentially works similar to rails rake db:seed task where I have a set of .json files in a specific folder, and when I run $ node seed it will run my seed.js file which takes all of those .json files and inserts the contents into their appropriate mongo collections based on the filename of the .json file.
Essentially I run $ node seed and it executes /seed.js which looks at /seeds/account.json, /seeds/customer.json, etc.
This way I can commit this code and then next developer can just run $ node seed and his mongo instance will be populated with some data to work with.
The problem i'm having is that the data that I got is from a dump of my collections in mongo so some sample data for account looks like this:
{ _id: { '$oid': '534d832177da4e0d38000001' },
id: 1,
name: something,
dateTime: '2014-04-15T14:06:09-05:00' }
Now when I run $ node seed, I get this error:
[Error: key $oid must not start with '$']
Is there any way to get around this error or am I going to have to remove all the $oid's from all my .json files?
seed.js:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/testdb');
var dir = './seeds';
var db = mongoose.connection;
// Show connection error if there is one
db.on('error', console.error.bind(console, 'Database Connection Error:'));
// If we successfully connected to mongo
db.once('open', function callback() {
var fs = require('fs'); // Used to get all the files in a directory
// Read all the files in the folder
fs.readdir(dir, function(err, list) {
// Log the error if something went wrong
if(err) {
console.log('Error: '+err);
}
// For every file in the list
list.forEach(function(file) {
// Set the filename without the extension to the variable collection_name
var collection_name = file.split(".")[0];
var parsedJSON = require(dir + '/' + file);
for(var i = 0; i < parsedJSON.length; i++) {
// Counts the number of records in the collection
db.collection('cohort').count(function(err, count) {
if(err) {
console.log(err);
}
});
db.collection(collection_name).insert(parsedJSON[i], function(err, records) {
if(err) {
console.log(err);
}
console.log(records[0]);
console.log("Record added as "+records[0]);
});
}
});
});
});
Or is there any libraries out there that already exist for this kind of task?
So there is a thing called the extended JSON syntax which is more of a spec and while supported by some driver implementations is yet to be implemented in the node native driver itself.
While there is one implementation I know of to work with converting these types, in the jsontomongo module for node, all of the types are not strictly supported. Yet as can clearly be seen in the code:
'use strict';
module.exports = function (query) {
var key, val;
for (key in query) {
if (!query.hasOwnProperty(key)) continue;
val = query[key];
switch (key) {
case '$date':
return new Date(val);
case '$regex':
return new RegExp(val, query.$options);
case '$undefined':
return undefined;
}
if (typeof val === 'object')
query[key] = module.exports(val);
}
return query;
};
Implementing the full specification or just the things you need such as ObjectId would be a fairly trivial exercise. You might even want to contribute your work as a node module yourself.
So that is essentially the sort of code you need to parse the object structure that results from parsing the JSON string.
http://docs.mongodb.org/manual/core/document/#field-names
The field names cannot start with the dollar sign ($) character.
Part of the mongodb spec as it uses $ to indicate operations like $inc or $unset.
Use this instead of $oid:
{ "_id" : ObjectId("5063114bd386d8fadbd6b004")}
Use mongodb-extended-json npm extension: https://www.npmjs.com/package/mongodb-extended-json
Here is the usage example taken from documentation:
var EJSON = require('mongodb-extended-json');
var BSON = require('bson');
var doc = {
_id: BSON.ObjectID(),
last_seen_at: new Date(),
display_name: undefined
};
console.log('Doc', doc);
// > Doc { _id: 53c2ab5e4291b17b666d742a, last_seen_at: Sun Jul 13 2014 11:53:02 GMT-0400 (EDT), display_name: undefined }
console.log('JSON', JSON.stringify(doc));
// > JSON {"_id":"53c2ab5e4291b17b666d742a","last_seen_at":"2014-07-13T15:53:02.008Z"}
console.log('EJSON', EJSON.stringify(doc));
// > EJSON {"_id":{"$oid":"53c2ab5e4291b17b666d742a"},"last_seen_at":{"$date":1405266782008},"display_name":{"$undefined":true}}
// And likewise, EJSON.parse works just as you would expect.
EJSON.parse('{"_id":{"$oid":"53c2ab5e4291b17b666d742a"},"last_seen_at":{"$date":1405266782008},"display_name":{"$undefined":true}}');
// { _id: 53c2ab5e4291b17b666d742a,
// last_seen_at: Sun Jul 13 2014 11:53:02 GMT-0400 (EDT),