Exclude fields from result in MongoDB monk - node.js

I want to exclude some fields from result.
I have code:
users = db.select('users');
users.find( {}, { sort: { points:1 }, privateKey:0, publicKey:0}, function(err,data){
res.send(data);
});
I want to exclude private and public key from results.
Can I do that using monk?

You can also do it like this:
users.find( {}, { sort: { points:1 }, fields : { privateKey:0, publicKey:0} },
function(err,data){
res.send(data);
}
);

According to documentation first argument in find is filter and second is projection .But you have used sort . It will not able to interpret . You are trying to confuse projection with sort .Sorting should be after find and projection.
You can write projection like { field1: <boolean>, field2: <boolean> ... }
Note :
The find() method always includes the _id field even if the field is not explicitly stated to return in the projection parameter.
users.find({}, { privateKey: 0, publicKey: 0 }).sort({points: 1}).toArray(
function (err, data) {
res.send(data);
});

For me, I need to use the .project() method:
const someFunction = async () => {
const result = await users
.find({}, { sort: { points: 1 })
.project({ privateKey: 0, publicKey: 0});
};

This is what worked for me for excluding the _id field.
const courseChapters = await db
.collection("users")
.find({}, { projection: { _id: 0 } })
.toArray();
So the example in the question would look something like this.
users.find(
{},
{ projection: { points: 1, privateKey: 0, publicKey: 0 } },
function (err, data) {
res.send(data);
}
);
Check out this other answer that says you may need the fields field instead of projection depending upon your driver

Related

Can mongodb send query pipelining with no loop?

I'm new to NodeJS and MongoDB.
I wanna get user's profile with one user's following list. If I use RDB, it was so simple with EQ join but I didn't have much experience of MongoDB, I don't know how.
Sample data below.
// list of users
[
{
_id: "oid_1",
nickname: "user_01",
link: "url/user_01"
},
{
_id: "oid_2",
nickname: "user_02",
link: "url/user_02"
},
{
_id: "oid_3",
nickname: "user_03",
link: "url/user_03"
}
...
]
user_01's followList
[
{
followOid: "foid_1",
userOid: "user_01"
},
{
followOid: "foid_2",
userOid: "user_02"
},
]
My solution is, get follow list, then use loop with follows.findOne() like below
const dataSet = [];
Follow.getFollowerList(userId) // for pipeline, use promise
.exec()
.then( async (result) => { // no async-await, no data output...
for (let data of result) {
let temp = await Users.getUserInfo( // send query for each data, I think it's not effective
data.userId,
{ nickname: 1, link: 1 }
);
dataSet.push(temp);
}
return dataSet;
})
.then((data) => {
res.status(200).json(data);
})
.catch( ... )
I think it's not best solution. If you are good at mongodb, plz save my life :)
thanks
One option would be to use aggregation.
const userId = 'Fill with UserId';
const pipe = [
{
'$match': {
'_id': userId
}
}, {
'$lookup': {
'from': 'followListCollectionName',
'localField': '_id',
'foreignField': 'userOid',
'as': 'followList'
}
}
];
const result = await UserModel.aggregate(pipeline);
and then you can find an array in result which contains one user with given Id ( and more if there are with same Id) and result[0].followList you can find follow objects as array
Second Option is to use virtuals
https://mongoosejs.com/docs/tutorials/virtuals.html
but for this schema of your collection needs some changes.
Good luck

Mongodb/mongoose omit a field in response [duplicate]

I have a NodeJS application with Mongoose ODM(Mongoose 3.3.1). I want to retrieve all fields except 1 from my collection.For Example: I have a collection Product Which have 6 fields,I want to select all except a field "Image" . I used "exclude" method, but got error..
This was my code.
var Query = models.Product.find();
Query.exclude('title Image');
if (req.params.id) {
Query.where('_id', req.params.id);
}
Query.exec(function (err, product) {
if (!err) {
return res.send({ 'statusCode': 200, 'statusText': 'OK', 'data': product });
} else {
return res.send(500);
}
});
But this returns error
Express
500 TypeError: Object #<Query> has no method 'exclude'.........
Also I tried, var Query = models.Product.find().exclude('title','Image'); and var Query = models.Product.find({}).exclude('title','Image'); But getting the same error. How to exclude one/(two) particular fields from a collection in Mongoose.
Use query.select for field selection in the current (3.x) Mongoose builds.
Prefix a field name you want to exclude with a -; so in your case:
Query.select('-Image');
Quick aside: in JavaScript, variables starting with a capital letter should be reserved for constructor functions. So consider renaming Query as query in your code.
I don't know where you read about that .exclude function, because I can't find it in any documentation.
But you can exclude fields by using the second parameter of the find method.
Here is an example from the official documentation:
db.inventory.find( { type: 'food' }, { type:0 } )
This operation returns all documents where the value of the type field is food, but does not include the type field in the output.
Model.findOne({ _id: Your Id}, { password: 0, name: 0 }, function(err, user){
// put your code
});
this code worked in my project. Thanks!! have a nice day.
You could do this
const products = await Product.find().select(['-image'])
I am use this with async await
async (req, res) => {
try {
await User.findById(req.user,'name email',(err, user) => {
if(err || !user){
return res.status(404)
} else {
return res.status(200).json({
user,
});
}
});
} catch (error) {
console.log(error);
}
In the updated version of Mongoose you can use it in this way as below to get selected fields.
user.findById({_id: req.body.id}, 'username phno address').then(response => {
res.status(200).json({
result: true,
details: response
});
}).catch(err => {
res.status(500).json({ result: false });
});
I'm working on a feature. I store a userId array name "collectedUser" than who is collected the project. And I just want to return a field "isCollected" instead of "collectedUsers". So select is not what I want. But I got this solution.
This is after I get projects from database, I add "isCollected".
for (const item of projects) {
item.set("isCollected", item.collectedUsers.includes(userId), {
strict: false,
})
}
And this is in Decorator #Schema
#Schema({
timestamps: true,
toObject: {
virtuals: true,
versionKey: false,
transform: (doc, ret, options): Partial<Project> => {
return {
...ret,
projectManagers: undefined,
projectMembers: undefined,
collectedUsers: undefined
}
}
}
})
Finally in my controller
projects = projects.map(i => i.toObject())
It's a strange tricks that set undefined, but it really work.
Btw I'm using nestjs.
You can do it like this
const products = await Product.find().select({
"image": 0
});
For anyone looking for a way to always omit a field - more like a global option rather than doing so in the query e.g. a password field, using a getter that returns undefined also works
{
password: {
type: String,
required: true,
get: () => undefined,
},
}
NB: Getters must be enabled with option { toObject: { getters:true } }
you can exclude the field from the schema definition
by adding the attribute
excludedField : {
...
select: false,
...
}
whenever you want to add it to your result,
add this to your find()
find().select('+excludedFiled')

How to delete an element from an array using mongoose

I'm a little bit stuck. I'm trying to delete an element from an array using mongoose.
I used :
my_collection.update({
user: req.query.user
}, {
$pullAll: { //or $pull
my_array: array[index] //= "elem1"
}
});
Unfortunately it really doesn't work...
Here is my document, if it could help :
{
"_id":"5a997cde9872f41085391f51",
"my_array":
["elem1",
"elem2",
"elem3",
"elem4"],
"user":"rodolphe",
"__v":0
}
Thank you for your help!
See $pullAll, it requires an array argument, you passed a string.
This is the error I get when I run your code:
MongoError: $pullAll requires an array argument but was given a string
Make sure you console.log your errors with .catch()
// mock data
const req = { query: { user: "rodolphe" } }
const array = ["elem1"];
const index = 0;
// update record
Collection.update({
user: req.query.user
}, {
$pullAll: { //or $pull
my_array: [array[index]] // WRAP WITH AN ARRAY
}
})
.then(res => console.log(res))
.catch(err => console.log(err));

Is it possible to get count of number of docs returned from find() query in mongoose

I am trying to get count of data fetched from the database using find() query in mongoose. Now can anyone tell me can i do something like below or do i have to write other function to do that
merchantmodel.find({merchant_id: merchant_id, rating: {'$ne': -1 }, review: {'$ne': "" }}, {'review':1, '_id':0}, {sort: {time_at: -1}}, function(err, docs) {
if (err) {
} else {
if (docs) {
console.log(docs[1].review);
console.log(docs.size()); // Here by writing something is it possible to get count or not
res.json({success: 1, message : "Successfully Fetched the Reviews"});
}
}
});
Convert returned value to array and then use length property
var query = { merchant_id : merchant_id, rating : { '$ne': -1 }, review: { '$ne': "" }};
var projection = { 'review':1, '_id':0 };
var options = { sort: { time_at: -1 } };
merchantmodel.find(query, projection, options).toArray(function(err, docs) {
if (err) {
throw(err);
}
console.log(docs[1].review);
console.log(docs.length);
res.json({success: 1, message : "Successfully Fetched the Reviews"});
});
You can simply do this:
console.log(docs.length);
The docs variable returned by the find() method is an array so docs.length would do the job.
The mongodb native way to do this would be:
db.collection.find( { a: 5, b: 5 } ).count()

Sails.js - Querying array size

// Item.js
schema: true,
attributes: {
testArray: {
type: 'array',
required: true,
array: true
}
}
I would like to find all items where the testArray attribute have a specific length.
I tried with this code below, but it doesn't work.
Item.find({testArray: {length: 2}}).exec(function (err, items) {
console.log(items);
});
I also tried with minLength, maxLength, size, but still no results.
Is there is a way to do that?
I'm using MongoDB via Sails.js/Waterline.
Actually this is in documentation
Model.where({ property: { '>': 100 }})
http://sailsjs.org/#!documentation/models
Another solution:
var query = { testArray: { $size: { $gt:2 } } };
Item.native(function(err, collection) {
collection.find(query).toArray(function(err, items) {
//items contains objects where testArray.length is greater than 2
});
});
You might run into problems depending on your mongodb version, then read http://www.mkyong.com/mongodb/mongodb-find-all-documents-where-an-array-list-size-is-greater-than-n/

Resources