only get a part of data from mongodb with nodejs - node.js

I have a problem with using asynchrone code in nodejs with mongodb.
In my current code I am writing some mongodb data in my console. Now I want to only get the "test1" from the data I receive. I would like to only get "test1" in the console and not the whole mongodb object. How would I archive this with?
MongoClient.connect(url,{ useNewUrlParser: true }, function(err, db) {
let dbo = db.db("list");
let cursor = dbo.collection('name').find({name: articleName});
let cont3nt = cursor.toArray(function(err, doc) {
console.log(doc);
return doc;
});
//console.log(cont3nt);
return cont3nt;
});
The console returns the following:
[ { _id: 5b6bf5072a0fd912380bcb3a, name: 'test1' } ]
Anyone got an idea?

As deceze suggested you could use projection.
In your example:
let cursor = dbo.collection('Bauteilname').find({name: articleName}, {"name":1, _id:0});
the "name":1 is for returning only the name field and the _id:0 is for not returning the _id field since it is always displayed and needs to be explicitly excluded.
source:
https://www.tutorialspoint.com/mongodb/mongodb_projection.htm

Related

Creating unique index via mongodb native driver

There is a code:
const { MongoClient } = require('mongodb')
const db = MongoClient.connect('mongodb://172.17.0.2:27017/test')
db
.then(
async dataBase => {
eduDb = dataBase.db('edu-service-accounts')
const accounts = eduDb.collection('accounts')
await accounts.createIndex({ email: 1 }, { unique: true })
accounts.insertOne({ email: '123' })
}
)
Code above creates an index, but that is no unique. I already read official docs for native mongoDB driver, but can't handle it.
And yes, I've deleted all old indexex before testing that code.
Can someone please show a code that really create an index with unique.
I mean not part of official doc, or something like that - I need code that works.
NOTE: I tested that code with local db and mlab - the same result.
Like the documentation says: db.createIndex(collectionname, index[, options], callback) the creation returns an index. Try to log the result of the callback. Maybe you are getting an error from the db.
Try something like:
// your connection stuff
accounts.createIndex({ email: 1 }, { unique: true }, function(err, result) {
if(err) {
console.log(err);
} else {
console.log(result);
}
});
After that please provide us the logs.

Object #<Promise> has no method 'limit'

when I run code
var collection = db.get('categories');
console.log(collection.find().limit(1).sort( { _id : -1 } ));
on nodejs using mongodb I am getting error Object # has no method 'limit' . I am a beginner to node and really stuck on this section of node
here is full code for geting last insert document.
router.post('/addcategory', function(req, res) {
// Set our internal DB variable
var db = req.db;
// Get our form values. These rely on the "name" attributes
var name = req.body.name;
var description = req.body.description;
// Set our collection
var collection = db.get('categories');
// Submit to the DB
collection.insert({
"name" : name,
"description" : description,
}, function (err, doc) {
if (err) {
// If it failed, return error
res.send("There was a problem adding the information to the database.");
}
else {
// And forward to success page
/******************/
console.log(collection.find().limit(1).sort( { _id : -1 } ));
/*************/
}
});
});
The key piece of missing information here was that you are using Monk, not the native MongoDB Node.JS driver. The command you have for find() is how you would use the native driver (with the changes suggested by #BlakesSeven above for asynchronity), but Monk works a little bit differently.
Try this instead:
collection.find({}, { limit : 1, sort : { _id : -1 } }, function (err,res) {
console.log(res);
});
The method is still asynchronous so you still need to invoke itm either as a promise with .then() or a callback. No methods are sychronous and return results in-line.
Also the result returned from the driver is s "Cursor" and not the object(s) you expect. You either iterate the returned cursor or just use .toArray() or similar to convert:
collection.find().limit(1).sort({ "_id": -1 }).toArray().then(function(docs) {
console.log(docs[0]);
});
Or:
collection.find().limit(1).sort({ "_id": -1 }).toArray(function(err,docs) {
console.log(docs[0]);
});
But really the whole premise is not correct. You seem to basically want to return what you just inserted. Event with the correction in your code, the returned document is not necessarily the one you just inserted, but rather the last one inserted into the collection, which could have occurred from another operation or call to this route from another source.
If you want what you inserted back then rather call the .insertOne() method and inspect the result:
collection.insertOne({ "name": name, "description": description },function(err,result) {
if (err) {
res.send("There was an error");
} else {
console.log(result.ops)
}
});
The .insert() method is considered deprecated, but basically returns the same thing. The consideration is that they return a insertWriteOpResult object where the ops property contains the document(s) inserted and their _id value(s),

Cannot Read property '_id' of undefined while using mongoose findOneandUpdate

I am using mean.io to make sports event management system.I am trying to update a model Player with rest api and it throws this error from mongoose:
{ _id: 5411c79895d600440c698fa1,
email: 'abc#bcd.com',
name: 'James Bond',
username: 'james.bond',
games: [ 5411bd54786cfe2420f1e27a ],
teams: [],
roles: [ 'authenticated' ] }
[TypeError: Cannot read property '_id' of undefined]
PUT /api/players/5411c79895d600440c698fa1 500 199.402 ms - 36
I also tried to delete the _id proterty from player but it doesnot works either.
the method i have used to update the model player is :
exports.update = function(req, res) {
var player = req.player;
player = _.extend(player, req.body);
console.log(player);
Player.findOneAndUpdate(req.params.playerId, player,{new:true}, function (err, updatedPlayer) {
console.log(err);
if (err) {
return res.status(500).json({
error: 'Cannot update the player'
});
}
res.json(updatedPlayer);
});
And also if i used the model.save method provided in the default package article of mean.io, it shows another error. I have extended the user model in player package app.js file. So whenever I try to update one field, the field that I have declared in app.js are required and the path required error from mongoose is thrown.
You have two issues in your update request.
First, the findOneAndUpdate expects a dict as the query and not just the id, so you should give it {_id: req.params.playerId} instead.
Second, passing a mongoose object as the update data is risky, instead you should convert it to a dict like this var _player = player.toObject() and then have _player be passed to the update request. Remember that you need to remove the _id param of_player because you can't change the _id of a document. Before doing the update just do delete _player._id and you should be fine. Also, new is set to true by default so you won't need the options dict.
Here is your working code:
var player = _.extend(req.player, req.body);
var _player = player.toObject();
delete _player._id;
var query = {_id: req.params.playerId};
Player.findOneAndUpdate(query, _player, function (err, updatedPlayer) {
...
});
But in this case you shouldn't even have to do the first operation. Since you just want to update the data of req.body you can do:
var query = {_id: req.params.playerId};
var data = {
$set: req.body,
};
Player.findOneAndUpdate(query, data, function (err, updatedPlayer) {
...
});
This will update all the fields of the player matching the query with the values from req.body.

Incorrect Subdocument Being Updated?

I've got a Schema with an array of subdocuments, I need to update just one of them. I do a findOne with the ID of the subdocument then cut down the response to just that subdocument at position 0 in the returned array.
No matter what I do, I can only get the first subdocument in the parent document to update, even when it should be the 2nd, 3rd, etc. Only the first gets updated no matter what. As far as I can tell it should be working, but I'm not a MongoDB or Mongoose expert, so I'm obviously wrong somewhere.
var template = req.params.template;
var page = req.params.page;
console.log('Template ID: ' + template);
db.Template.findOne({'pages._id': page}, {'pages.$': 1}, function (err, tmpl) {
console.log('Matched Template ID: ' + tmpl._id);
var pagePath = tmpl.pages[0].body;
if(req.body.file) {
tmpl.pages[0].background = req.body.filename;
tmpl.save(function (err, updTmpl) {
console.log(updTmpl);
if (err) console.log(err);
});
// db.Template.findOne(tmpl._id, function (err, tpl) {
// console.log('Additional Matched ID: ' + tmpl._id);
// console.log(tpl);
// tpl.pages[tmpl.pages[0].number].background = req.body.filename;
// tpl.save(function (err, updTmpl){
// if (err) console.log(err);
// });
// });
}
In the console, all of the ID's match up properly, and even when I return the updTmpl, it's saying that it's updated the proper record, even though its actually updated the first subdocument and not the one it's saying it has.
The schema just in case:
var envelopeSchema = new Schema({
background: String,
body: String
});
var pageSchema = new Schema({
background: String,
number: Number,
body: String
});
var templateSchema = new Schema({
name: { type: String, required: true, unique: true },
envelope: [envelopeSchema],
pagecount: Number,
pages: [pageSchema]
});
templateSchema.plugin(timestamps);
module.exports = mongoose.model("Template", templateSchema);
First, if you need req.body.file to be set in order for the update to execute I would recommend checking that before you run the query.
Also, is that a typo and req.body.file is supposed to be req.body.filename? I will assume it is for the example.
Additionally, and I have not done serious testing on this, but I believe your call will be more efficient if you specify your Template._id:
var template_id = req.params.template,
page_id = req.params.page;
if(req.body.filename){
db.Template.update({_id: template_id, 'pages._id': page_id},
{ $set: {'pages.$.background': req.body.filename} },
function(err, res){
if(err){
// err
} else {
// success
}
});
} else {
// return error / missing data
}
Mongoose doesn't understand documents returned with the positional projection operator. It always updates an array of subdocuments positionally, not by id. You may be interested in looking at the actual queries that mongoose is building - use mongoose.set('debug', true).
You'll have to either get the entire array, or build your own MongoDB query and go around mongoose. I would suggest the former; if pulling the entire array is going to cause performance issues, you're probably better off making each of the subdocuments a top-level document - documents that grow without bounds become problematic (at the very least because Mongo has a hard document size limit).
I'm not familiar with mongoose but the Mongo update query might be:
db.Template.update( { "pages._id": page }, { $set: { "pages.$.body" : body } } )

NodeJS + MongoDB: Getting data from collection with findOne ()

I have a collection "companies" with several objects. Every object has "_id" parameter. I'm trying to get this parameter from db:
app.get('/companies/:id',function(req,res){
db.collection("companies",function(err,collection){
console.log(req.params.id);
collection.findOne({_id: req.params.id},function(err, doc) {
if (doc){
console.log(doc._id);
} else {
console.log('no data for this company');
}
});
});
});
So, I request companies/4fcfd7f246e1464d05000001 (4fcfd7f246e1464d05000001 is _id-parma of a object I need) and findOne returns nothing, that' why console.log('no data for this company'); executes.
I'm absolutely sure that I have an object with _id="4fcfd7f246e1464d05000001". What I'm doing wrong? Thanks!
However, I've just noticed that id is not a typical string field. That's what mViewer shows:
"_id": {
"$oid": "4fcfd7f246e1464d05000001"
},
Seems to be strange a bit...
You need to construct the ObjectID and not pass it in as a string. Something like this should work:
var BSON = require('mongodb').BSONPure;
var obj_id = BSON.ObjectID.createFromHexString("4fcfd7f246e1464d05000001");
Then, try using that in your find/findOne.
Edit: As pointed out by Ohad in the comments (thanks Ohad!), you can also use:
new require('mongodb').ObjectID(req.params.id)
Instead of createFromHexString as outlined above.
That's because _id field in mongo isn't of string type (as your req.params.id). As suggested in other answers, you should explicitly convert it.
Try mongoskin, you could use it like node-mongodb-native driver, but with some sugar. For example:
// connect easier
var db = require('mongoskin').mongo.db('localhost:27017/testdb?auto_reconnect');
// collections
var companies = db.collection('companies');
// create object IDs
var oid = db.companies.id(req.params.id);
// some nice functions…
companies.findById();
//… and bindings
db.bind('companies', {
top10: function(callback) {
this.find({}, {limit: 10, sort: [['rating', -1]]).toArray(callback);
}
});
db.companies.top10(printTop10);
You can use findById() which will take care of the id conversion for you.
company = Company.findById(req.params.id, function(err, company) {
//////////
});
In case these didn't work for you, this worked for me for accessing a blog post:
const getSinglePost = async (req, res) => {
let id = req.params.id;
var ObjectId = require('mongodb').ObjectId;
const db = await client.db('CMS');
const data = await db.collection("posts").findOne({ _id: ObjectId(id) })
if (data) {
res.status(200).send(data)
} else res.status(400).send({ message: "no post found" })
}

Resources