Mongoose remove _id and __v before sending to the front end - mongodb

When I get data from mongo via mongoose with...
const allAssets = await assets
.find({ company })
.sort([['createdAt', -1]])
.exec();
res.status(200).json({ assets: allAssets });
I always get _id and __v but I dont want to send these to the front end, is there a way I can easly say I dont want these values or remove them before sending them?
{
"indistructable": true,
"_id": "5e345c2dc84be8995a5b4cf2",
"baseUri": "https://api.website.com/nameco8/",
"company": "jnameco8",
"description": "asset",
"image": "myimage.png",
"name": "jim",
"supply": 100,
"createdAt": "2020-01-31T16:56:13.816Z",
"updatedAt": "2020-01-31T16:56:13.816Z",
"__v": 0
},
I have tried adding
__v: {type: Number, select: false},
_id: { type: mongoose.Schema.Types.ObjectId, select: false },
to my schema but when saving to the schema I then get an error
"document must have an _id before saving"

As far as I believe schemas are for writes to restrict unknown fields from being written to documents which make your documents look similar across your collection, but if you need to remove few fields in read then try projection in .find() :
const allAssets = await assets
.find({ company }, {_id :0, __v:0})
.sort([['createdAt', -1]])
.exec();
res.status(200).json({ assets: allAssets });

Schema.find()
.select("-_id -__v")
.exec()
.then(result =>{
console.log(result);
})
In addition to #whoami - fakeFaceTrueSoul's answer, you can also add multiple <" -fieldName "> to your select statement in find()

Related

findOneAndUpdate - document query > 1000

So I have a collection that has over 1million documents clearly, I don't need to search 1000 or more documents as it should only be updating the latest document.
const nowplayingData = {"type":"S",
"station": req.params.stationname,
"song": data[1],
"artist": data[0],
"timeplay":npdate};
LNowPlaying.findOneAndUpdate( nowplayingData,
{ $addToSet: { history: [uuid] } },
{ upsert: true, sort: {_id:-1} },
function(err) {
if (err) {
console.log('ERROR when submitting round');
console.log(err);
}
});
I have added a sort on it, so that it is able to get the latest one first, but if the document is not in there and it's the first time the document is being added then the way the script is written will query all documents to find.
When really it only needs to look at the last say 100 documents or even better if timeplay is in the last 5 minutes.
You can do something like:
const nowplayingData = {
"type":"S","station": req.params.stationname, "song": data[1], "artist": data[0],
"timeplay":{$gte: beforeFiveMin}};
But this will create a new document almost every time...so you will need to maintain it...

insert element into db only if it doesnt exist

Hy i am using mongoose.
I have this query that inserts about 30 elements into my database:
await Code.insertMany(information);
Information looks like:
[
{
discount: 20,
url: '...',
code: "...",
sponsorUrl: "...",
sponsorAccount: "..."
},
]
The url is unique. I want to add again 30 items into the database but it could be that 10 items from 30 are already saved in the database
How can i achieve that? I could loop it but is there an better solution?
I dont want to have duplicated urls
The upsert = true option creates the object if the url does not already exist in a document in the collection.
for (var i of information){
Code.update(
{'url' : i.url },
{$set : i},
{upsert : true, multi : true},
function(err, doc){
if(err) throw err;
console.log(doc);
}
)
}

Can anyone generate mongodb query for my scenario

I am new to MongoDB and using Mongoose to manage data to and from MongoDB. I have a collection having below structure:
var post= new Schema({
message: String,
created_by_user_id: mongoose.Schema.Types.ObjectId,
created_at: Date,
likes: [new Schema({liked_by_user_id: mongoose.Schema.Types.ObjectId})]
});
Below is the above collection with dummy documents:
[{
"_id": "5c0254c13a22f222ceb861ad",
"message": "from pppr",
"created_by_user_id": "5c0253e9a53bed2165c0625c",
"likes": [
{
"_id": "5c027a6fff5fcb5ab180e20c",
"liked_by_user_id": "5c0253e9a53bed2165c0625c"
},
{
"_id": "5c028e46abc09775c10d767b",
"liked_by_user_id": "5c0234c1d8832b6af3b4f4a6"
}
],
"created_at": "2018-12-01T09:30:41.943Z",
"__v": 0
},
{
"_id": "5c0254c13a22f222ceb861ad",
"message": "from pppr",
"created_by_user_id": "5c0253e9a53bed2165c0625c",
"likes": [
{
"_id": "5c027a6fff5fcb5ab180e20c",
"liked_by_user_id": "5c0253e9a53bed2165c0625c"
},
{
"_id": "5c028e46abc09775c10d767b",
"liked_by_user_id": "5c0234c1d8832b6af3b4f4a6"
}
],
"created_at": "2018-12-01T09:30:41.943Z",
"__v": 0
}]
Now, I am trying to get all documents along with status which will indicate that, whether I have liked the respective post or not. In request, I am also send my user id.
Basically, On my wall, system should show all the posts created by either me or by my friends along with extra status in each document which will show whether I liked the respective post or not.
I am saving user friends in separate collection named as "userfriends". The structure of this collection is given below:
var userfriends = new Schema({
user_id_1: mongoose.Schema.Types.ObjectId,
user_id_2: mongoose.Schema.Types.ObjectId,
created_at: Date
});
I just want to get all posts along with that extra field. So, you can ignore the userfriends collection this is just for guiding you more.
Can any one help me on this? What will be the query which can fulfill my requirement?
Thanks in Advance
You can use $addFields along with the $in aggregation operator
db.collection.aggregate([
{ "$addFields": {
"status": { "$in": [mongoose.Types.ObjectId(userId), "$likes.liked_by_user_id"] }
}}
])
It will add a new fields to your every post document with the boolean value

Return Array of Populated Objects in Mongoose

I have a DB for a forum with 3 collections: Threads, Posts, Comments.
I have a GET request to return an individual forum thread that populates each thread with user's posts, and each user post with any comments that were made on it which is working as shown below:
router.get('/:id', (req, res) => {
Threads
.findById(req.params.id)
.lean()
.populate({path: 'posts'})
.exec(function(err, docs){
var options = {
path: 'posts.comments',
model: 'comments'
};
if(err) return res.json(500);
Threads.populate(docs, options, function(err, thread){
res.json(thread);
})
})
})
When this GET request is made it will return a forum thread like so:
{
"_id": "5924ad549a08ed4e70a9c89f",
"title": "Testing Full Schemas",
"author": "Mongoose",
"content": "Schema Content",
"posts": [
{
"_id": "5924ad999a08ed4e70a9c8a0",
"content": "New Schema Post",
"user": "Mongodb",
"comments": [
{
"_id": "5924ae489a08ed4e70a9c8a1",
"comment": "New Schema Content",
"user": "Matt",
"likes": 0,
"created": "2017-05-25T12:41:58.319Z"
}
]
}
Now I need a GET request to return an array of ALL threads (router.get('/')) with each threads posts and comments to be populated. I tried to replace:
Threads
.findById(req.params.id)
with
Threads
.find(req.params.id)
but it is not working. Does anyone have an idea of how this could be accomplished?
To return all the threads, simply use find without any match condition in it.
Also, populate posts and 'posts.comment' in the find query itself, you don't need to do it in the callback of the find.
use population across multiple levels
**Try this:
Threads.find({})
.populate({
path:'posts',
populate :{
path : comments
}
})
.exec(function(err,docs){
//docs is the array of all the Threads, with posts and comments populated within it
})
Read Mongoose Documentation on Populate and Nested Population for detailed information. ( Search for Populating across multiple levels)
findById and findOne returns a single document, where find returns a cursor. Once you go through the cursor of find, you are at the end, and there are no more documents.
Using find query:-
ModelName.find({_id:req.params.id})
.populate({
path:'posts',
populate :{
path : comments
}
},(error,data)=>{
if(error){
res.json(error);
}
else{
res.json(data);
}
})
Using findById query:-
ModelName.findById(req.params.id)
.populate({
path:'posts',
populate :{
path : comments
}
},(error,data)=>{
if(error){
res.json(error);
}
else{
res.json(data);
}
})

Mongoose query where value is not null

Looking to do the following query:
Entrant
.find
enterDate : oneMonthAgo
confirmed : true
.where('pincode.length > 0')
.exec (err,entrants)->
Am I doing the where clause properly? I want to select documents where pincode is not null.
You should be able to do this like (as you're using the query api):
Entrant.where("pincode").ne(null)
... which will result in a mongo query resembling:
entrants.find({ pincode: { $ne: null } })
A few links that might help:
The mongoose query api
The docs for mongo query operators
$ne
selects the documents where the value of the field is not equal to
the specified value. This includes documents that do not contain the
field.
User.find({ "username": { "$ne": 'admin' } })
$nin
$nin selects the documents where:
the field value is not in the specified array or the field does not exist.
User.find({ "groups": { "$nin": ['admin', 'user'] } })
I ended up here and my issue was that I was querying for
{$not: {email: /#domain.com/}}
instead of
{email: {$not: /#domain.com/}}
Ok guys I found a possible solution to this problem. I realized that joins do not exists in Mongo, that's why first you need to query the user's ids with the role you like, and after that do another query to the profiles document, something like this:
const exclude: string = '-_id -created_at -gallery -wallet -MaxRequestersPerBooking -active -__v';
// Get the _ids of users with the role equal to role.
await User.find({role: role}, {_id: 1, role: 1, name: 1}, function(err, docs) {
// Map the docs into an array of just the _ids
var ids = docs.map(function(doc) { return doc._id; });
// Get the profiles whose users are in that set.
Profile.find({user: {$in: ids}}, function(err, profiles) {
// docs contains your answer
res.json({
code: 200,
profiles: profiles,
page: page
})
})
.select(exclude)
.populate({
path: 'user',
select: '-password -verified -_id -__v'
// group: { role: "$role"}
})
});
total count the documents where the value of the field is not equal to the specified value.
async function getRegisterUser() {
return Login.count({"role": { $ne: 'Super Admin' }}, (err, totResUser) => {
if (err) {
return err;
}
return totResUser;
})
}
Hello guys I am stucked with this. I've a Document Profile who has a reference to User,and I've tried to list the profiles where user ref is not null (because I already filtered by rol during the population), but
after googleing a few hours I cannot figure out how to get this. I
have this query:
const profiles = await Profile.find({ user: {$exists: true, $ne: null }})
.select("-gallery")
.sort( {_id: -1} )
.skip( skip )
.limit(10)
.select(exclude)
.populate({
path: 'user',
match: { role: {$eq: customer}},
select: '-password -verified -_id -__v'
})
.exec();
And I get this result, how can I remove from the results the user:null colletions? . I meant, I dont want to get the profile when user is null (the role does not match).
{
"code": 200,
"profiles": [
{
"description": null,
"province": "West Midlands",
"country": "UK",
"postal_code": "83000",
"user": null
},
{
"description": null,
"province": "Madrid",
"country": "Spain",
"postal_code": "43000",
"user": {
"role": "customer",
"name": "pedrita",
"email": "myemail#gmail.com",
"created_at": "2020-06-05T11:05:36.450Z"
}
}
],
"page": 1
}
Thanks in advance.