mongodb update failes on express session - mongodb

I am using passportjs for authentication. I am using mongodb to store express sessions. The document that gets saved contains 3 fields _id, session, expires.
When I try to update the document using mongoose it does not. It does however find the document but does not update.
Would there be any lock on the document? When I try to update from mongo console it does...
Please help.
here is my code:
var conditions = { '_id' : req.sessionID};
var update = { $set: { 'ip': '111.11.111.1112' }};
Sessions.update(conditions, update, function (err, res) {
if (err) return callback("FAILED");
return callback("SUCCESS");
});
This is my schema.....
var mongoose = require('mongoose');
// define the schema for our user model
var sessionsSchema = mongoose.Schema({
_id : String,
session : String,
ip : String,
expires : String
});
// create the model for users and expose it to our app
module.exports = mongoose.model('sessionsIP', sessionsSchema, 'sessionsIP');

Related

Argument passed in must be a single String of 12 bytes or a string of 24 hex characters, Mongoose ObjectId err

I actually searched a ton and I saw a ton of mentions of my problem here but none of the things I tried helped me fix the issue i'm having.
I have a Room Scheme that looks like this:
const ObjectId = mongoose.Schema.ObjectId;
const roomSchema = mongoose.Schema({
users: [{
type: ObjectId,
ref: 'User'
}],
messages: [{
type: ObjectId,
ref: 'Message',
}],
post: {
type: ObjectId,
ref: 'Post'
}
});
As you can see I have an array of users with ref to another schema Users
I'm trying to query all the Rooms that has a User ObjectId in it (search ObjectId in an array).
while I can easily get this with querying mongo from cmd using this:
db.users.find({users:ObjectId('THE_OBJECT_ID')});
when I try to get the same while using mongoose it fails with:
Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
Here is how my route and find looks like:
app.route('/rooms/list/:user_id')
.get((req, res) => {
var query = { users: "USER_ID" };
Room.find(query ).populate('messages').then((data) => {
res.status(200).json(data);
}).catch((err) => {
console.log(err);
});
})
I tried to create type of object ID and use it but it still doesn't work.
var mongoose = require('mongoose'),
userId = 'THE_USER_ID';
var id = mongoose.Types.ObjectId(userId);
and than
Rooms.find({'users': id });
but it still doesn't work.
I also tried altering my query search using $in, $elemmatch it worked on cmd but failed when querying using mongoose.
Any help would be appreciated.
Issue :
If you check this :
var query = { users: "USER_ID" };
(Or)
userId = 'THE_USER_ID';
var id = mongoose.Types.ObjectId(userId);
What are you trying to do here ? You are passing in string USER_ID or THE_USER_ID as input and trying to convert it to type of ObjectId(). But string inside ObjectId() has certain restrictions which is why mongoose is failing to convert passed in string value to ObjectId() and getting error'd out.
Try this code :
Code :
const mongoose = require('mongoose');
app.route('/rooms/list/:user_id')
.get((req, res) => {
var query = { users: mongoose.Types.ObjectId(req.params.user_id) };
Room.find(query).populate('messages').then((data) => {
res.status(200).json(data);
}).catch((err) => {
console.log(err);
});
})
Your input should be value of user_id (Which will be string) - Convert it to ObjectId() and then query DB. So value of user_id should be a string that obeys ObjectId()'s restrictions, You can take string from one of existing doc's ObjectId() & test your get api.

Receiving Data from Mongodb using Mongoose [duplicate]

I just started learning MongoDB and mongoose. Currently I have the following structure:
database -> skeletonDatabase
collection -> adminLogin
When I run db.adminLogin.find() from the command line I get:
{ "_id" : ObjectId("52lhafkjasfadsfea"), "username" : "xxxx", "password" : "xxxx" }
My connection (this works, just adding it FYI)
module.exports = function(mongoose)
{
mongoose.connect('mongodb://localhost/skeletonDatabase');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
console.log('Conntected To Mongo Database');
});
}
My -js-
module.exports = function(mongoose)
{
var Schema = mongoose.Schema;
// login schema
var adminLogin = new Schema({
username: String,
password: String
});
var adminLoginModel = mongoose.model('adminLogin', adminLogin);
var adminLogin = mongoose.model("adminLogin");
adminLogin.find({}, function(err, data){
console.log(">>>> " + data );
});
}
My console.log() returns as >>>>
So what am I doing wrong here? Why do I not get any data in my console log? Thanks in advance for any help.
mongoose by default takes singular model names and pairs them with a collection named with the plural of that, so mongoose is looking in the db for a collection called "adminLogins" which doesn't exist. You can specify your collection name as the 2nd argument when defining your schema:
var adminLogin = new Schema({
username: String,
password: String
}, {collection: 'adminLogin'});
Had a problem with injecting it within an express route for my api so I changed it thanks to #elkhrz by first defining the schema and then compiling that one model I want to then pull like so:
app.get('/lists/stored-api', (req, res) => {
Apis.find(function(err, apis) {
if (err) return console.error(err);
res.send(apis);
});
});
I wouldn't send it to the body, I would actually do something else with it especially if you plan on making your API a production based application.
Run through this problem and read up on possible proper ways of rendering your data:
How to Pass Data Between Routes in Express
Always a good idea to practice safe procedures when handling data.
first compile just one model with the schema as an argument
var adminLogin = mongoose.model('adminLogin', adminLogin);
in your code adminLogin does not exist, adminLoginModel does;
after that ,instead to
adminLogin.find({}, function(err, data){
console.log(">>>> " + data );
});
try this
adminLogin.find(function (err, adminLogins) {
if (err) return console.error(err);
console.log(adminLogins);
is important the "s" because mongo use the plural of the model to name the collection, sorry for my english...

Mongoosejs can't query with findById

I have a meteor application saving stuff to mongodb and I have an api I wish to make and expose via REST.
express = require 'express'
mongoose = require 'mongoose'
app = express()
mongoose.connect process.env.MONGO_URL
Account = mongoose.model 'users',
profile:
available: Boolean
app.get "/accounts/meta/:account_id", (req, res) ->
account = Account.findById req.params.account_id
, (error, account) ->
if account?
res.jsonp
account: account
else
res.jsonp 404,
error: "Account not found"
app.listen 2000
The problem is that I can't query by the id's I see in my database. For example I have this user:
{
"_id": "zcdsHuKr5dTh3xHz5",
"createdAt": 1373188729653,
"last_seen": 1373465529548,
"profile": {
....
If I go to /accounts/meta/zcdsHuKr5dTh3xHz5 it says 'Cast to ObjectId failed for value "zcdsHuKr5dTh3xHz5" at path "_id"'. I tried in every possible way to query for my document without luck. Any ideas?
The problem is that you need to define a schema for your model to tell Mongoose that your _id field is a String instead of the standard ObjectId in this collection:
AccountSchema = new mongoose.Schema
_id: String
profile:
available: Boolean
Account = mongoose.model 'users', AccountSchema
Seems that your _id field isn't an ObjectId. The method findById on Mongoose expects:
id objectid, or a value that can be casted to one
So, if your _id in fact isn't an ObjectId, you should query using findOne method
account = Account.findOne { "_id" : req.params.account_id }
The currently propagated answer is not a good idea. Don't change the schema for your model to tell Mongoose that your _id field is a String. That is a bad idea in terms of validation and should be considered a hack.
Try this instead:
If you want to query for an _id in mongoose, you have to cast the _id to ObjectId
AccountSchema = new mongoose.Schema({
_id: ObjectID(),
profile: {
available: Boolean
});
Account = mongoose.model('users', AccountSchema);
Mongoosejs requires you to cast the id in the query as well (I didn't find anything about this in the mongoose documentation either):
account = Account.findOne({ "_id" : mongoose.Types.ObjectId(req.params.account_id) });

Can't fetch with Mongoose but working with Mongo shell

I am playing around with Mongoose and Node.
A want to be able to save a Backbone model, and fetch the saved models from Mongo via Mongoose.
I am able to save models but I can't fetch them via Mongoose. I can access them via the Mongo shell with no problems using:
db.users.find()
My code is:
var mongoose = require('mongoose'),
userschema = mongoose.Schema({name: 'string', email: 'string'}),
db = mongoose.createConnection('localhost', 'test'),
User = db.model('User', userschema);
exports.save = function(req, res){
var userobj = req.body,
newuser = new User(userobj);
newuser.save(function(err){
if(err){
res.send(err);
}
else{
res.send(newuser);
}
});
};
exports.fetch = function(req, res){
var users = User.find();
res.send(users);
}
When I send a request and executes my fetch function the server responds with
{
"options": {
"populate": {}
},
"_conditions": {},
"_updateArg": {},
"op": "find"
}
It is like I am not on the right Collection or something.
User.find() doesn't return the results of the query; those are passed to the callback that you provide as a parameter to find.
exports.fetch = function(req, res) {
User.find(function(err, users) {
res.send(users);
});
};
If you don't provide a callback, then a Query object is returned (which is what you're seeing in the response).

How to access a preexisting collection with Mongoose?

I have a large collection of 300 question objects in a database test. I can interact with this collection easily through MongoDB's interactive shell; however, when I try to get the collection through Mongoose in an express.js application I get an empty array.
My question is, how can I access this already existing dataset instead of recreating it in express? Here's some code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
mongoose.model('question', new Schema({ url: String, text: String, id: Number }));
var questions = mongoose.model('question');
questions.find({}, function(err, data) { console.log(err, data, data.length); });
This outputs:
null [] 0
Mongoose added the ability to specify the collection name under the schema, or as the third argument when declaring the model. Otherwise it will use the pluralized version given by the name you map to the model.
Try something like the following, either schema-mapped:
new Schema({ url: String, text: String, id: Number},
{ collection : 'question' }); // collection name
or model mapped:
mongoose.model('Question',
new Schema({ url: String, text: String, id: Number}),
'question'); // collection name
Here's an abstraction of Will Nathan's answer if anyone just wants an easy copy-paste add-in function:
function find (name, query, cb) {
mongoose.connection.db.collection(name, function (err, collection) {
collection.find(query).toArray(cb);
});
}
simply do find(collection_name, query, callback); to be given the result.
for example, if I have a document { a : 1 } in a collection 'foo' and I want to list its properties, I do this:
find('foo', {a : 1}, function (err, docs) {
console.dir(docs);
});
//output: [ { _id: 4e22118fb83406f66a159da5, a: 1 } ]
You can do something like this, than you you'll access the native mongodb functions inside mongoose:
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/local');
var connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error:'));
connection.once('open', function () {
connection.db.collection("YourCollectionName", function(err, collection){
collection.find({}).toArray(function(err, data){
console.log(data); // it will print your collection data
})
});
});
Update 2022
If you get an MongoInvalidArgumentError: The callback form of this helper has been removed. error message, here's the new syntax using async/await:
const mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/productsDB');
const connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error:'));
connection.once('open', async function () {
const collection = connection.db.collection("Products");
collection.find({}).toArray(function(err, data){
console.log(data); // it will print your collection data
});
});
I had the same problem and was able to run a schema-less query using an existing Mongoose connection with the code below. I've added a simple constraint 'a=b' to show where you would add such a constraint:
var action = function (err, collection) {
// Locate all the entries using find
collection.find({'a':'b'}).toArray(function(err, results) {
/* whatever you want to do with the results in node such as the following
res.render('home', {
'title': 'MyTitle',
'data': results
});
*/
});
};
mongoose.connection.db.collection('question', action);
Are you sure you've connected to the db? (I ask because I don't see a port specified)
try:
mongoose.connection.on("open", function(){
console.log("mongodb is connected!!");
});
Also, you can do a "show collections" in mongo shell to see the collections within your db - maybe try adding a record via mongoose and see where it ends up?
From the look of your connection string, you should see the record in the "test" db.
Hope it helps!
Something else that was not obvious, to me at least, was that the when using Mongoose's third parameter to avoid replacing the actual collection with a new one with the same name, the new Schema(...) is actually only a placeholder, and doesn't interfere with the exisitng schema so
var User = mongoose.model('User', new Schema({ url: String, text: String, id: Number}, { collection : 'users' })); // collection name;
User.find({}, function(err, data) { console.log(err, data, data.length);});
works fine and returns all fields - even if the actual (remote) Schema contains none of these fields. Mongoose will still want it as new Schema(...), and a variable almost certainly won't hack it.
Go to MongoDB website, Login > Connect > Connect Application > Copy > Paste in 'database_url' > Collections > Copy/Paste in 'collection' .
var mongoose = require("mongoose");
mongoose.connect(' database_url ');
var conn = mongoose.connection;
conn.on('error', console.error.bind(console, 'connection error:'));
conn.once('open', function () {
conn.db.collection(" collection ", function(err, collection){
collection.find({}).toArray(function(err, data){
console.log(data); // data printed in console
})
});
});
I tried all the answers but nothing worked out, finally got the answer hoe to do it.
var mongoose = require('mongoose');
mongoose.connect('mongodb://0.0.0.0:27017/local');
// let model = require('./test1');
setTimeout(async () => {
let coll = mongoose.connection.db.collection(<Your collection name in plural form>);
// let data = await coll.find({}, {limit:2}).toArray();
// let data = await coll.find({name:"Vishal"}, {limit:2}).toArray();
// let data = await coll.find({name:"Vishal"}, {projection:{player:1, _id:0}}).toArray();
let data = await coll.find({}, {limit:3, sort:{name:-1}}).toArray();
console.log(data);
}, 2000);
I have also mentioned some of the criteria to filter out. Delete and update can also be done by this.
Thanks.
Make sure you're connecting to the right database as well as the right collection within the database.
You can include the name of the database in the connection string.
notice databasename in the following connection string:
var mongoose = require('mongoose');
const connectionString = 'mongodb+srv://username:password#hosturl.net/databasename';
mongoose.connect(connectionString);