Mongo $in query works in mongo but not in sails - node.js

Basically the query works in mongo but not in sails controller:
db.membermodel.find({identifier:{$in:["2","3","4"]}); // works
MemberModel.find({
identifier:{$in:["2","3","4"]},
}).then(function(members){
// doesn't work
});
data returned:
{ "_id" : ObjectId("52d1a484f2b5e88cb5d4072c"), "identifier" : "2", "deviceToken" : "token2"}
{ "_id" : ObjectId("52d1a487f2b5e88cb5d4072d"), "identifier" : "3", "deviceToken" : "token3"}
Thanks,
Mars

This isn't the way to do in queries with Waterline. You simply set the attribute you're selecting to the array value:
MemberModel.find({
identifier:["2","3","4"]
}).exec(function(err, members){
...
});
If you really need to use low-level Mongo features, you can get an instance of the native collection with
MemberModel.native(function(err, collection) {
//do native mongo driver stuff with collection
}

Hard to understand how the model is being queried but I suggest you to "spy" what's Mongo getting as the MVC framework query, due to this is not a direct query to Mongo, it's passed through the framework.
I'm quite sure you're still developing so you have access to your mongo instance, restart it using full profile (the trick is everything is slow under 1ms)
mongod --profile=1 --slowms=1 &
Tail the resulting log which normally is in
/var/log/mongodb/mongodb.log
with the command
tail -f /var/log/mongodb/mongodb.log
Send your query again and check what MongoDb is executing.

Related

Is there a way to access mongodb node.js driver functionality while still using mongoose for schema definition?

What I am really trying to do is to make indexes for filtering and string matching of documents based on their property values.
I know that mongodb has built in operators such as $text that are very helpful with this sort of functionality.
I'm not sure how to access these operators while using mongoose, or if there are any methods i need to use to access them.
I want to use mongoose to still define schema and models but need the functionality of native mongodb.
Is this possible?
Below are my views, Please add if I miss anything or if something needs to be modified or well-explained :
1. You will still be able to use mongoDB's native functionalities on using Mongoose models.
2. Mongoose is a kind of wrapper on top of native mongoDB-driver.
3. It would be very useful if you want to have schema based collections/data.
4. Additionally it would provide few more features than native mongoDB's driver. You might see few syntax differences between those two.
5. Few examples like `.findByIdAndUpdate()` & `.populate()` are mongoose specific, which has equivalent functionalities available in mongoDB driver/mongoDB as well.
6. In general it's quiet common to define mongoose models and use those over mongoDB's functionality in coding(As in node.js - You would write all of your same DB queries on Mongoose models, queries that you execute in DB).
Point 2 :
Mongoose is an object document modeling (ODM) layer that sits on top of Node's MongoDB driver. If your coming from SQL, it's similar to an ORM for a relational database.
Point 3 :
In code if you're using mongoose models to implement your write queries, unless you define a field in model - it wouldn't be added to DB though you pass it in request. Additionally you can do multiple things like making a field unique/required etc.. it's kind of making your mongoDB data look like schema based. If your collections data is more like random data(newsfeed kind of thing where fields are not same for each document & you can't predict data) then you might not care of using mongoose.
Point 6 :
Let's say you use mongo shell or a client like mongo compass/robo3T and execute a query that's like this :
db.getCollection('yourCollection').find(
{
$text: {
$search: 'employeeName',
$diacriticSensitive: false
},
country: 'usa'
},
{
employee_id: 1,
name: 1
}
).sort({ score: { $meta: 'textScore' } });
you would do same on mongoose model(As yourCollectionModel is already defined) :
yourCollectionModel.find(
{
$text: {
$search: 'employeeName',
$diacriticSensitive: false
},
country: 'usa'
},
{
employee_id: 1,
name: 1
}
).sort({ score: { $meta: 'textScore' } });
You would see key functionality difference more on writes rather than reads while using mongoose, though all the above is not about performance - If you ask me, I can say you might see much performance gains using mongoose.
Ref : Mongoose Vs MongoDB Driver

Mongod is crashing when querying the database

I have an AWS instance with nodejs and mongod running. The collection I am trying to query from has roughly 289248 documents in there.
Here is the code I am using to query my data:
var collection = db.collection('my_collection');
collection.find({ $and: [
{"text" : {$regex : ".*"+keyword+".*"}},
{"username" : username}
] }).limit(10).toArray(function(err, docs) {
Now originally, I was having issues querying just a username collection.find({"username":username}) because there are so many entries in mongo. So I started limiting my code and in the mongo console, I can set a limit of 30 and it results the results I am looking for.
However, then when I run this application on nodejs, when I query this command, it crashes my mongod service and I have to restart it. On the node server, limit of 1 works fine but limit of 5 does not. I can't simply use limit of 1 if there are many more results in the database. What can I do?
Does not using $and make a difference? :
collection.find({text:{$regex:".*"+keyword+".*"},username: username})
I also wonder if the 'text' is a text index in which case it should be '$text'.
I also note that you use two variables in your query expression, and wonder if you have verified that those variables are defined.

"Hook" to Save function Globally - something like post event

I want to keep track(by loging to another collection) on any Create , Update or Delete operation that happen in Mongodb.
My existing app (NodeJs) uses mongoose for repository. I'm trying to log every time something has changed(CUD) in the DB. Simple solution would be to add logs everywhere i modify to db, but i have so many methods.I wonder if i can "hook" on a post Save globally? something like middleware to Mongo.
Use below hook on schema on which you want to log(this is only for save function)
schema.post('save', function(next){
//log data using this here
next();
})
Refer to this link:
http://mongoosejs.com/docs/middleware.html
as per this link:
> use myDb
switched to db myDb
> db.getProfilingLevel()
0
> db.setProfilingLevel(2)
{ "was" : 0, "slowms" : 1, "ok" : 1 }
> db.getProfilingLevel()
2
> db.system.profile.find().pretty()
reference: MongoDB logging all queries

How to keep MongoDB from wrapping integers with NumberInt

I have a web app that posts a JSON request to a Node/Express server, which then inserts a new document into a local MongoDB database using the latest version of the mongodb Node module. When I view the documents using MongoChef, all integers are wrapped with NumberInt(x).
"shirts" : {
"adult-x-large" : NumberInt(2),
"youth-small" : NumberInt(1),
"adult-small" : NumberInt(1),
"adult-medium" : NumberInt(1)
}
I'm sure these wrappers are useful for certain applications, but I really don't want my JSON filled with them. Is there a way to disable this? I'm not sure if this is a MongoDB issue, a MongoChef issue, or something else entirely.
It is just a display part in MongoChef. If you view the data in "TreeView", it should show the type as Int32 with just numeric value.
As long as the datatye is "Int32", it should be correct and as expected.
MongoChef JSON View:-
MongoChef Tree View:-
RoboMongo Json View:-

runCommand equivalent for nodejs-native-mongodb

I'm trying to utilize MongoDB 2.4 experimental text search feature from within nodejs. The only problem is, native nodejs mongo drivers don't seem to support collection-level runCommand, as far as I can tell.
The Mongo shell syntax looks like this:
db.collection.runCommand( "text", { search : "Textvalue" } );
There is a db.command / db.executeDbCommand function it appears, but I don't know how to choose a collection and run the text command using it (if it is possible), as it needs to be on the collection level and not the db level.
Any help would be appreciated
I managed to get it working through a combination of Asya Kamsky's comment, by utilizing
this.db.command({text:"collection" , search: "phrase" }).
The problem was it isn't returned like a standard result so a toArray() call was failing. Instead, I put the callback directly inside:
this.db.command({text:"collection" , search: "phrase" }, function(err, cb){

Resources