mongoose: $match isn't find documents - node.js

I created a schema Machine:
import mongoose from 'mongoose';
import moment from 'moment';
const Schema = mongoose.Schema;
const MachineSchema = new Schema({
device_name: {
type: String,
unique: true
},
state: String,
count_pings: {
type: Number,
default: 1
},
created_at: {
type : Number,
default: moment().format('x')
},
last_work_time_at: {
type : Number,
default: moment().format('x')
}
});
export default mongoose.model('Machine', MachineSchema);
I send the query using aggregate framework to MongoDB:
require('dotenv').config();
import mongoose from 'mongoose';
import Machine from './models/machine';
const fiveMinutesAgo = moment().subtract(process.env.INTERVAL_TIME_IN_MINUTES, 'minutes').format('x');
Machine.aggregate([
{$match: {last_work_time_at: {$lt: fiveMinutesAgo}}},
{$project: {_id: 1, device_name: 1, last_work_time_at: 1}}
])
.then(results => {
console.log(results);
})
I want to get all documents for which value of last_work_time_at is less than value of fiveMinutesAgo.
I use mongoose of version 4.11.7.
Here, for example the document stored in collection:
{
"_id" : ObjectId("59a6c8a5811e812935f3c6d4"),
"device_name" : "cg0011",
"state" : "unworking",
"last_work_time_at" : 1504102558069.0,
"created_at" : 1504102558069.0,
"count_pings" : 15844,
"__v" : 0
}
I have same else 10 documents and for which absolutely every value of field last_work_time_at is less than value of `fiveMinutesAgo, but result of query is empty array.
I don't understand why don't get any documents by query. I'm thinking that somewhere made a little error and that is why isn't search it still.
Please, help me. Thanks in advance.

Related

Use arrayFilters in order to update a property of an object in nested array of objects, with Mongoose

I have a collection in MongoDb that has documents "flights" which contain a field array of objects. I want to update one property of one object at a time. In order to do so, I have to use two filters: One in order to select the document that I want to update, and a second one to select the object in the array.
I am using arrayFilters with Mongoose as follows:
This is my Flight shema
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const flightSchema = new Schema({
flightName :{ type : String, required :true},
sits : {type : Array, required : true}, //[{n:1, d:f, s:f}]
origin : {type: String, required : true},
destination : {type : String, required: true},
departure : {type : Date, required : true},
arrival : {type : Date, required : true}
})
module.exports = mongoose.model('Flight', flightSchema)
// Models/Flight.js
{
flightName: a164651,
origin: Monterrey,
detination: Cancun,
sits: [{
sitNumber: 1,
isAvailable: true,
isSuspended: false
}, {
sitNumber: 2,
isAvailable: true,
isSuspended: false
}]
}
Lets imagine that I want to update the property IsSuspended from false to true in the object with sitNumber : 2.
//Controllers dashboard.js
blockSit : async (req, res) => {
try {
const flight = req.body.flightName
const sit = req.body.sitToBlock //sit es 2
const updateSit = await Flight.updateOne(
{ "flightName": flight},
{ "$set" : {"sits.$[si].isSuspended": true} },
{ "arrayFilters": [{ "si.sitNumber": sit} ]}
)
console.log(updateSit)
} catch (error) {
console.log(error)
}
}
As far as I can see my sintaxis is correct. However I keep receiving the following error message:
Error: Could not find path "sits.0.sitNumber" in schema
I do not have to use arrayfilters necesarily. I am open to try any other solution that allows me to update a property in a nested array of objects with mongoose.
It looks like your sits field is array of sub-documents but there is not a schema to describe the fields. Try defining the schema.
const sitSchema = new Schema({
sitNumber: Number,
isAvailable: Boolean,
isSuspended: Boolean,
// etc
});
// in the flight schema
sits: [sitSchema],
This is how I solved:
First I needed to use the method findOneandUpdate in Mongoose.
Also, I added to arrayFilters the property new and set it to true.
blockSit : async (req, res) =>{
try {
const flight = req.body.flightName
console.log(flight)
const sit = req.body.sit
console.log(sit)
const updateSit = await Flight.findOneAndUpdate(
{"flightName" : flight},
{ "$set" : {"sits.$[si].isSuspended" : true, "sits.$[si].isAvailable": false} },
{"arrayFilters" :[ { "si.sitNumber" :sit} ], new : true}
)
res.send(updateSit)
}
catch (error) {
console.log(error)
}
},

MongoDB: executionTimeMillis increased when adding index

I am pretty confused to why making the searched fields to be "index" is making the query "theoretically" slower.
I have a not very big collection of items (6240) and all of them have the following structure.
const SomeSchema = new mongoose.Schema({
data: String,
from: {
type: Number,
},
to: {
type: Number,
},
timeStamp: {
type: Date,
default: new Date()
}
})
SomeSchema.set('toJSON', {
getters: true,
transform: (doc, ret) => {
delete ret.from
delete ret.to
return sanitizeSensitiveProperties(ret)
}
})
export const Some = mongoose.model('Some', SomeSchema, 'somethings')
The strange thing came when after trying to improve the query I changed the schema to be
...
from: {
type: Number,
index: true
},
to: {
type: Number,
index: true
},
...
With this schema I run the following query
db.rolls.find({from: {$lte: 1560858984}, to: {$gte: 1560858984}}).explain("executionStats")
This are the results NOTE THAT THE 1st ONE is the one without index
"executionTimeMillis" : 6,
"totalKeysExamined" : 0,
"totalDocsExamined" : 6240,
"executionTimeMillis" : 15,
"totalKeysExamined" : 2895,
"totalDocsExamined" : 2895,
Does this result make any sense, or is just the mongo .explain() function messing around?
As you can see I am using the Mongoose Driver in the version ^5.5.13 and I am using Mongo in the version 4.0.5

mongodb date insert like using mongoose

I am inserting bulk records in mongodb. I am using the native DB drivers to do this, as the performance is much higher. At other points in my application, i am using mongoose. The problem I am having is that mongoose translates the date into a different format whereas mongodb native just inserts it as the number of seconds since 1970. So later queries in mongoose based off that date do not work.
Here's my mongoose schema:
var MySchema = new Schema({
name : { type: String, required: true },
updatedAt : Date
});
And my mongo db mass insert:
var newRec = {
name : entry.Name,
updatedAt : Date.now
};
newRecords.push(newRec);
MySchema.collection.insert(newRecords, function(err, newRecs) {
res.json(newRecs.ops);
});
This produces in the DB:
{
"_id": {
"$oid": "562818ecf24d540f0053a38d"
},
"name": "Cool Record",
"updatedAt": 12312423512
}
Whereas if it was run through Mongoose it would produce:
{
"_id": {
"$oid": "561fd90285b5e73f5626f74e"
},
"name": "Cool Record",
"updatedAt": {
"$date": "2015-10-20T20:01:17.553Z"
}
}
If going through mongoose, queries like this work well:
MySchemda.find({ updatedAt : { $gt: lastSynced }}).exec();
But do not work otherwise.
Date.now is a number representing milliseconds since 1970. While it conceptually represents a date, it isn't actually a Date:
var x = Date.now;
typeof x;
// "number"
You need to switch your schema to be:
var MySchema = new Schema({
name : { type: String, required: true },
updatedAt : Number
});
alternately, you can use:
var newRec = {
name: entry.Name,
updatedAt: new Date()
}
and keep your schema as it is.
You may use it like this:
Define the date type and the default value, then create a variable which can be defined as your schema use year : new Date this would help a lot to set the date.
var songSchema = new mongoose.Schema({
name : String,
year : {type : Date, default : Date.now},
singer : String,
});
var song = mongoose.model("song", songSchema);
var xyz= new song({
name : "abcd",
year :new Date, // to set the date first set new Date
singer : "aabbccdd",
});
You can use setDate , setMonth, setYear method to solve the issues.There are more methods defined under the object year .You can out further at the documentation of mongoose.
xyz.save(function(err, songs){
if(err)
winston.log("Something is wrong"+ " "+ err);
else {
songs.year.setDate(03);
songs.year.setMonth(03);
songs.year.setYear(2015);
winston.log(songs);
}
});

Mongoose MongoDB: updating objects in a nested array

I've got the following schema
var UserSchema = new Schema({
emp_no: Number,
skills: [{
skill: {
type: Schema.Types.ObjectId,
ref: 'Skill'
},
startDate: {type: Date},
}]
});
I'm then trying to update the startDate of one particular skill. I've tried several differents ways, one of them being:
User.findOne({emp_no: req.body.emp_no}, function (err, user) {
user.update( {'skills._id': 123}, {'$set': {
'skills.$.startDate': req.body.startDate
}}
}
This particular code gives: err: 'cannot use the part (skills of skills._id) to traverse the element
The actual object looks like
{
"_id" : ObjectId("5469753de27a7c082203fd0a"),
"emp_no" : 123,
"skills" : [
{
"skill" : ObjectId("547d5f3021d99d302079446d"),
"startDate" : ISODate("2014-12-02T06:43:27.763Z")
"_id" : ObjectId("547d5f8f21d99d3020794472")
}
],
"__v" : 108
}
Any ideas what I'm doing wrong?
When you call update on a model instance like you're doing here, the first parameter is the update operation to apply to that document, as the document to update is already uniquely identified by its _id.
Instead, use Model.update to do this all in one operation:
User.update(
{emp_no: req.body.emp_no, 'skills._id': 123},
{'$set': {
'skills.$.startDate': req.body.startDate
}},
function(err, numAffected) {...}
);

MongoDB default values are not saved, instead re-calculated at runtime

I'm building a simple REST app on the Yeoman Express MVC generator with MongoDB.
This is my MongoDB/Mongoose model (updated with complete update.js model):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var UpdateSchema = new Schema({
title: String,
text: String,
authors: String,
url: String,
imageUrl: String,
dateCreated: { type: Date, default: Date.now },
reloadNeeded: { type: Boolean, default: true }
});
mongoose.model('Update', UpdateSchema);
This is what the data looks like in the Mongo client:
> db.updates.find();
{ "_id" : ObjectId("5476453f8920d05ecdef4eec"), "title" : "Hello World", "text" : "yoda yoda" }
{ "_id" : ObjectId("547653748920d05ecdef4eed"), "title" : "Hihi", "text" : "mookie" }
And this is the JSON output from my Express app:
[
{"_id":"5476453f8920d05ecdef4eec","title":"Hello World","text":"yoda yoda","reloadNeeded":true,"dateCreated":"2014-11-27T10:50:10.078Z"},
{"_id":"547653748920d05ecdef4eed","title":"Hihi","text":"mookie","reloadNeeded":true,"dateCreated":"2014-11-27T10:50:10.078Z"}
]
So, dateCreated and reloadNeeded are set at runtime - but I'd rather want them set (and persisted) when I create the documents. What's going on?
Update: seems like values are persisted if I create from Mongoose rather than the MongoDB shell.
Do you use mongoose for data model? If it so, default values will be created on document construction http://mongoosejs.com/docs/2.7.x/docs/defaults.html
Anyway I assume the reason is in defaults

Resources