Weird Mongoose. I get crap from findOne's doc. - mongodb

Here is what my script look like:
UserModel.findOne(
{userId:'xx123456'},
function(err, doc) {
if (err) {
next(err);
} else if (! doc) {
next( 'findOne: User not found. Input: ' + JSON.stringify(data)));
} else {
next(null, {status:true,
message:'User is found' ,
data:doc
});
}
}
);
When I run unit test in command line, doc is the mongo Document. e.g. {userId:'xx123456', name:"My Name' }
However, when I make a web app calling this function passing exactly the same userId, doc.userId is empty. However, I can find the data in doc._doc why is that?
I have another site that return the full document from "doc" normally. Why there is inconsistency...
I have to do this to normalize the data: if (docs) docs = JSON.parse(JSON.stringify(docs));

Not really sure what's happening, but I'd first try a UserModel.find({}); Do this to see what, if anything, returns. If nothing returns you have a problem.
Also, one issue I've seen is that Mongoose is case sensitive. Make sure 'userId' is not supposed to be something like 'userid.' Command line will work (as far as I've seen) with the wrong case. Mongoose / Node will not.

Related

text index required for $text query in the MongoDB with Express

I built a Express back-end which is connected to local MongoDB
when I create a post to find out the specific term, it returns the error like this
MongoError: text index required for $text query
How can I fix this error?
this is my Express code
app.post("/api/search",(req,res)=> {
const term = req.body.searchTerm;
console.log(term); // Here I can check the request coming well
MongoClient.connect(url,(err,db)=> {
if(err) throw err;
const dbo = db.db("Exercise");
dbo.collection("exercise")
.find({$text:{$search:term}})
.toArray((error, result) => {
if (error) {
console.log(error);
return;
} else {
console.log("Success");
res.send(result);
}
});
});
});
Thank you in advance!
What you can do to solve your problem is simple. You can create a "text" on the field that you want search in you collection like this:
db.reviews.createIndex( { comments: "text" } )
Note: assumes "comments" is the field as seen in the docs
However, for the best results you might want to create a dynamic default Search index in MongoDB Atlas. It's free and easy. Because it is a dynamic default, you do not need to do any configuration. The results and performance will likely be better if you are powering a search experience.
I hope this info helps.

mongoose query return empty array if filter has a field name that is camel cased

The following issue was with some code written in express/nodejs.
I experienced something I could not find any material in regards,
I encountered an issue whereas making a find query with mongoose returned an empty array.
After tinkering I discovered it was due to the key used (customerRef) being camel cased
I tried to tweak other fields from and to camelcase and got the same issue.
see example here:
const lastCart = await Cart.findOne({ customerRef: customer._id }, function(err, docs) {
if (err) {
console.log('TCL: err', err);
}
console.log('TCL: docs', docs); //result = []
});
then went and tweaked my database objects from:
{
....
"customerRef" : "5dfcd194ca19972b888d66c2",
....
}
to:
{
....
"customerref" : "5dfcd194ca19972b888d66c2",
....
}
then the query worked as expected:(customerRef >>> customerref)
const lastCart = await Cart.findOne({ customerref: customer._id }, function(err, docs) {
if (err) {
console.log('TCL: err', err);
}
console.log('TCL: docs', docs); //result is now ok = [...]
});
Now to top this off here's another bit of info:
I use studio 3T for mMongoDB and over there I do not have this issue when making queries.
I would appreciate any and all explanation on this behavior aswell as alternatives if possible.
See my full repo here:
(My skills are novice at best so I apologize in advanced and welcome any feedback)
https://github.com/Darkmift/MEAN-SuperMarket/blob/master/backend/app/controllers/userController.js#L121
So after some time I have concluded the issue was with my use of the mongo shell program (Studio 3t)
at the time I was not aware how to properly insert an ObjectId.
When using the built in query one must add:
{
...
"customerRef" : ObjectId(RefId)
...
}
and NOT:
{
...
"customerRef" : "RefId"
...
}

Meteor-Mongo: Error handling for findone

I am trying to handle errors using findOne in meteor-mongo.
From this stackoverflow question, it appears that I should be able to handle errors by doing collection.findOne({query}, function(err, result){ <handleError> }, but doing so results in an errormessage:
"Match error: Failed Match.OneOf, Match.Maybe or Match.Optional validation"
The following code works:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}),
};
}, App);
The following code does not:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}, function(err,result){
if(!result){
return {}
};
}),
};
}, App);
What am I doing wrong and how should I be resolving this error? Is this a meteor specific error?
Any help is greatly appreciated!
What kind of error are you exactly trying to handle with your callback?
Meteor's findOne is different from node's mongodb driver's findOne that the post you link to uses.
The expected signature is:
collection.findOne([selector], [options])
There is no callback involved, since the method runs synchronously (but is reactive).
If you want to return a default value when the document is not found, you can simply use a JS logical OR:
// Provide an alternative value on the right that will be used
// if the left one is falsy.
theData.findOne({_id: theID}) || {};
A more rigorous approach would be to compare its type with
typeof queryResult === 'undefined'
Note that if theData collection is fed by the above subscription Meteor.subscribe('thePubSub'), I doubt Meteor will have time to populate the collection on the client by the time you query it…

Can't find user by name with Monk / Mongo

I'm working on a CRUD application with Node, Mongo & Monk.
I'd like to find a record by username, and then update it.
But I'm unable to find a record, this code isn't working:
// GET User Profile
router.get('/userprofile', function(request,response){
var db = request.db;
var userName = request.body.username;
var collection = db.get('usercollection');
collection.findOne({
"username": userName
},{},function(e,user){
response.render('userprofile', {
"user": user
});
});
});
The "findOne" method doesn't return anything, and the "user" object ends up empty.
Remove the middle empty object from the signature for the findOne() method signature for the query to work:
Note: The way you are getting the userName is for when the request method is a POST, here you are doing a GET so you need to use the request.query property. More details here
var userName = request.query.username;
collection.findOne({"username": userName}, function(e,user){
response.render('userprofile', { "user": user });
});
If you want to update then you can use the update() method, suppose you want to update the username field to change it to 'foo', the following stub shows how you can do the update:
var u = collection.update({ "username": userName }, { "$set": { username: 'foo' } });
u.complete(function (err, result) {
console.log(err); // should be null
console.log(result); // logs the write result
});
Ok, I found out the problem.
Chridam's code was correct, but I also needed to change my form from a GET to a POST. Once I did that, the form POSTed and mongo could see request.body.username (it was null before) and look up my user using Chridam's code.
After reading Chridam's revised answer, was also able to get it to work with GET.
Now working on the update code..

WaterlineJs find() with no criteria and fields/select provided does not work

I am trying to fetch all the records but with selected fields, I have tried the following ways but none works:
Post.find(
{
where: {},
select: ['title']
}
);
Post.find(
{},
{
fields: {
title: 1
}
}
);
As this answer points out, the fields param "WILL work as long as you pass other params with it such as limit or order."
Alternatively, if you want this throughout your application, you could define a custom toJSON function for your model, under attributes. If not, you could still define it under some other (e.g. filter) and use map to return the custom objects instead of the default model. Remember to take care of the control flow while using map though. Use async/promises/raw logic to avoid returning before all objects are processed.
The issue has been resolved in sails-mongo latest version:
https://github.com/balderdashy/waterline/issues/1098
Thanks
I've played with trying to get above answer to use limit or order to kick in the projection to no avail.
I did see this in the docs located here:
http://sailsjs.org/documentation/reference/waterline-orm/models/native
With an out of the box solution for exactly what you're doing (pasted here for ease of use).
Pet.native(function(err, collection) {
if (err) return res.serverError(err);
collection.find({}, {
name: true
}).toArray(function (err, results) {
if (err) return res.serverError(err);
return res.ok(results);
});
});
Swap out the response base things and change Pet to Post and, this ought to work in the sails console:
Post.native(function(err, collection) {
if (err) throw new Error(err);
collection.find({}, {
title: true
}).toArray(function (err, results) {
if (err) throw new Error(err);
console.log(results);
});
});
You'll still get the _id field, and if you don't want that then hit the Mongo docs on not getting those hint(title: true, _id: false)hint
Hope this helps!