Mongoose query where value is not null - mongodb

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.

Related

MongoDB - Add / update to list of objects on document

I have a user collection, and each user has a list of products. I need to update a product using it's ID or add the product if it doesn't exist.
How can I update the product by it's id?
User Collection:
{
"_id": {
"$oid": "5fc06554266266edf5643231"
},
"products": [
{
"id": 123,
"name": "test product"
}
]
}
Using the following code I'm able to add the product, but can't update the product by it's ID.
db.users.updateOne({_id: ObjectId('5fc06554266266edf5643231')}, {
'$addToSet': {
'products': {
'id': 123,
'name': 'foobar'
}
}
}, {upsert:true})
Well, i will recommend to you to re-think your schema.
Maybe you need to create a collection called Products and in the user collection put all the id's of the products on a field called product. Then you can create a query with a populate function. Something like this
const user = await User.find(query, options)
.then(async (result) => result)
.catch((err) => logger.info(err));
const populateProducts = await Products.populate(user, populateProductsOptions)
.then(async (data) => data)
.catch((err) => logger.info(err));
But if you don't want to modify your schema you have to do several querys. There is no way to do this in single query. You have to search the document first:
If document exist:
db.users.updateOne( {_id: 123456 , yourQueryProduct ,
false ,
true);
db.users.updateOne( {_id: 123456: 123456 } ,
{$pull: {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
db.users.updateOne( {_id: 123456: 123456 } ,
{$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
else if document don't exist you can addToSet directly
The issue is that on this line: db.users.updateOne({_id: "5fc06554266266edf5643231"}
The _id field is being interpreted as a String, but the document you want to update saves its _id as an ObjectId. All you have to do it make it an ObjectId is this:
db.users.updateOne({_id: ObjectId("5fc06554266266edf5643231")}, {
'$addToSet': {
'products': {
'id': 123,
'name': 'foobar'
}
}
}, {upsert:true})

mongodb find and update one with multiple conditions

{
roomId: "id",
questions:{
q1:{
user1:"user1's work"
}
}
}
I'm trying to query mongodb with multiple conditions, that roomId has to match, and questions must be q1, and in q1 there must be a user1.
Here's what I've tried so far. Using and operator, but doesn't seems to work.For now I'm using find, as I read in the docs that updateMany has the same query selector as find.
const result = await collection.find({
$and: [
{
roomId: roomId,
},
{
questions: {
currentQuestion: {
userName,
},
},
},
],
});
My schema:
{
roomId: "id",
roomName:"roomName",
questions:{
question1:{
user1:"user1's work",
userN: "userN's work"
},
questionN:{
user1:"",
userN:""
}
}
}
My expected input , (roomId, currentQuestion, userName) for query conditions,"userWork" to be inserted to what's under userName (user1 - userN).
Expected output, that the user's work gets updated with "userWork", under the right room, right currentQuestion and the right user.
You need this query I think:
db.collection.find({
"roomId": "id",
"questions.q1.user1": {
$exists: true
}
})
This query find a roomId which match your 'id' and then, check if exists the element questions.q1.user1.
Mongo playground example here
PS: You said update but... what do you want to update?
Assuming your schema is like
{
roomId: "id",
questions: {
q1: {
user1: "user1's work",
currentQuestion: "currentQuestion1"
}
}
}
Then, the query to update the currentQuestion field whose match the id and has existing questions.q1.user1 is this:
db.collection.update({
"roomId": "id",
"questions.q1.user1": {
$exists: true
}
},
{
"$set": {
"questions.q1.currentQuestion": "new question"
}
})
Example here
Note that if currentQuestion is one level up, you only have to modify $set object.
If you are not asking for this, please provide a complete schema, example input and expected output.

Mongoose remove _id and __v before sending to the front end

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()

MongoDB Regex $and $or Search Query

I am trying to construct a query that will accept multiple fields that can be searched over using regex for partial field matching that also has a hard constraint on other fields.
Example:
Collection: "Projects"
Required Information: { propertyId: "abc", clientId: "xyz" }
Fields to be Searched: name, serviceType.name, manager.name
Currently, I have a query like this, but if there are no results it returns all the results, which isn't helpful.
{
'$and': [
{ propertyId: '7sHGCHT4ns6z9j6BC' },
{ clientId: 'xyz' },
{ '$or':
[
{ name: /HVAC/gi },
{ 'serviceType.name': /HVAC/gi },
{ 'manager.name': /HVAC/gi }
]
}
]
}
If anyone has any insight into this it would be much appreciated.
Example Document:
{
_id: "abc",
propertyId: "7sHGCHT4ns6z9j6BC",
clientId: "xyz"
name: "16.000.001",
serviceType: {
_id: "asdf",
name: "HVAC"
},
manager: {
_id: "dfgh",
name: "Patrick Lewis",
}
}
The expected result is to only find documents where propertyId = 7sHGCHT4ns6z9j6BC AND one at least one of the following keys: name, serviceType.name, or manager.name match an inputted string, in this case, it's HVAC and if none of the regex fields match, then return nothing.
UPDATE
The issue was with MongoDB, after restarting it, everything worked.
Try following script:
db.collection.find({
$and:[
{propertyId:"7sHGCHT4ns6z9j6BC"},
{
$or:[
{name: /HVAC/i},
{"serviceType.name": /HVAC/i},
{"manager.name": /HVAC/i}
]
}]
})
Query above will return a document or documents if and only if propertyId matches and either of name, serviceType.name or manager.name matches desired regex.

How can I aggregate collection and group by field count

I have a collection of users that looks something like this:
{
"_id": ObjectId("54380a817a4b612a38e87613"),
"email": "email#email.com",
"ogp": [BIG NESTED COLLECTION... {}, {}, {}]
"created": ISODate("2012-02-28T23:10:07Z"),
"o_id": ObjectId("5438096f7a4b612a38e445f4")
"geo": {"country":"US", "city":"Seattle", "longitude": 123, "latitude":123}
}
I'd like to get all the users location and group them by country and total. Something like this:
[ {country:"US",total:250,000}, {country:"GB",total:150,000}, ... ]
Currently I'm just grabbing all of the documents and parsing it on the server:
db.users.find({'geo.country': {$ne: null},'geo.city': {$ne: null}}, {'geo.country':1}, function(err, doc) {
var data;
doc = _.groupBy(doc, function(par) { return par.geo.country; });
data = [];
return _.each(doc, function(item, key, obj) {
return data.push([key, obj[key].length]);
});
});
The problem with this is there are 600,000+ documents and the query takes about 1 minute to execute. Would the "aggregate" function would help speed up this query? If so how would I do it?
This should do it:
db.myCollection.aggregate([
{"$group": {_id: "$geo.country", count:{$sum:1}}}
])