Mongoose query with a list in the model - node.js

In my model, I have this field:
…
shows: [{
startAt: Number,
endAt: Number
}],
…
I need a query to select all objects that have a show that hasn't started yet. In other words, I want to find all models that have at least one startAt that is smaller than a given time.
Is this possible? And if so, how can I do it?

As I didn't have any test data, I couldn't test what worked. Now I do, and #joao is absolutely correct.
It seems like Mongoose doesn't care that shows is a list. It was as simple as writing
<model>.find().where('shows.startAt').gt(<constant>).exec(callback);

Related

Mongo db find operation query ($gte, $lt) is not working

I had a problem using query with MongoDB.
The problem was solved but I wanted to check if there was any other approach I could have taken.
At first, my model (Ad) had a property of price: {type: String}, and I tried to find by queries $gte and $lt to get ads with a price within a given range.
After reading online I figured that query operations are not working on String type properties.
Then even after changing the type to Number - price: {type: Number} - the find function didn't work properly on the price, even though on other properties which were type Number it worked as it should.
In the end, I just deleted the whole database and reupload it, and then everything worked properly (haven't changed a thing).
Has anyone had this kind of problem and solved it differently?
I'll first start by assuming you're using mongoose as the "types" you've pasted look like mongoose schema types.
You need to separate these two concepts:
The schema that represents data at the app level
The actual data in the DB.
Let's say I have this schema for a certain collection:
{ name: String }
But in the actual database there is only one document in that collection that looks like this:
{ price: 5, product_id: 1 }
Then when I query the data what do you expect to happen? do you expect mongoose to automatically generate a name for that document and delete the actual fields?
The reason it didn't "work" as you intended was that all the values were saved as string, changing the Schema does not retroactively update the database, so when you use $lt and $gte it uses string comparison which means "10" is less than "9" because that's how string comparison work.
The schema does help with newly inserted data and can cast it to the right type if supported, for that you should check the docs with what values are available.

Mongoose, How to limit the query based on the sum of a field in the document

I have a document in the shape of
const Model = mongoose.Schema({
something1: {type:String},
someNumber1:{type:Number},
something2: {type:String},
someNumber2:{type:Number},
aFloatNumber: {type:Number}
)}
and after indexing the document like
Model.index({something1:1 , something2:1 , aFloatNumber:1})
for better performance which I hope I am doing right and please correct me if I am doing it wrong.
I am trying to query usign syntax:
const model = await Model.find({
$and:[{something1:anInput}, {something2:anotherInput}]})
.sort(aFloatNumber)
now I want to limit the returned query as it could be a very large list to improve performance, however, this limit changes based on an input. Basically I want the mongoose to keep adding someNumber1 together and stop returning after it gets larger than the input number. Something like the code bellow:
const model = await Model.find({
$and:[{something1:anInput}, {something2:anotherInput}]})
.sort(aFloatNumber)
.limit( sum(someNumber1) >= theInputNumber )
So basically my questions are:
Am I indexing the document correctly based on my query?
Does it make any difference on the performance to limit the query since it is sorting the data and I think it is going to check all the document to be able to sort it?
If it makes a huge difference on the performance, what is the correct syntax for it as I am going to make this query a lot in my application?
You're asking for skip function of mongodb which is like offset in sql
https://docs.mongodb.com/manual/reference/operator/aggregation/skip/

How to properly use 'exist' function in mongodb like in sql?

I'm using Node.js + mongodb. I have few documents in my collection and i want to know does my collection have any document matched my condition. Of course i can simply use
myModel.find({ myField: someValue }) and check is anything comes or not. But i want to use solution like sql provides exists keyword? Help me, please
Edit: my bad. I forget to tell that "performance first".
MongoDB's $exists actually doesn't help you very much to find out if a certain document exists in your collection. It is used for example to give you all documents that have a specific field set.
MongoDB has no native support for an sql like exists. What you can use, however, is myModel.findOne({ myField: someValue }) and then check if it is null.
To enhance performance you can tell MongoDB to only load the object id via projection, like this:
myModel.findOne({ myField: someValue }, {_id: 1})
There is an exist mechanism in mongodb, I'll demonstrate a sample below.
For example below, I'm looking for records that have tomato.consensus fields and that it's empty, so I can delete them or avoid them. In case I was looking for "tomato.consensus": Dublin, I'd change Null to Dublin, to match that.
I hope this is helpful, if not fire away any questions
tomato
----consensus
db.movieDetails.updateMany({$and: [
{"tomato.consensus": {$exists: true} },
{"tomato.consensus": null} ] },
]})

Is there a way to only read a certain field from Mongoose?

I have a DB with a couple of levels deep nested stuff, sometimes pretty big.
now i have searched the doc and google/so, but couldn't find a simple answer:
if the schema is like:
{
roomId : String,
created : Date,
teacher : String,
students : Object,
problems : Array
}
is there a way to just read the roomId of every entry?
Not return the whole thing, but just an array of the roomIds?
(usecase: i want to make a list of all saved rooms, therefore i need absolutely nothing of all the other data, just the IDs. I want to avoid that overhead)
i'm pretty sure it can be done, but couldn't find how
Yes, use a projection
Model.findOne({...}, {roomId: 1})....

Node.js + Mongoose / Mongo & a shortened _id field

I'd like the unique _id field in one of my models to be relatively short: 8 letters/numbers, instead of the usual Mongo _id which is much longer. Having a short unique-index like this helps elsewhere in my code, for reasons I'll skip over here. I've successfully created a schema that does the trick (randomString is a function that generates a string of the given length):
new Schema('Activities', {
'_id': { type: String, unique: true, 'default': function(){ return randomString(8); } },
// ... other definitions
}
This works well so far, but I am concerned about duplicate IDs generated from the randomString function. There are 36^8 possible IDs, so right now it is not a problem... but as the set of possible IDs fills up, I am worried about insert commands failing due to a duplicate ID.
Obviously, I could do an extra query to check if the ID was taken before doing an insert... but that makes me cry inside.
I'm sure there's a better way to be doing this, but I'm not seeing it in the documentation.
This shortid lib https://github.com/dylang/shortid is being used by Doodle or Die, seems to be battle tested.
By creating a unique index on _id you'll get an error if you try to insert a document with a duplicate key. So wrap error handling around any inserts you do that looks for the error and then generates another ID and retries the insert in that case. You could add a method to your schema that implements this enhanced save to keep things clean and DRY.

Resources