Problem with MongoDB's aggregate function, getting erromessage not understanding why - javascript

For school assignment, I've got to execute several MongoDB queries regarding specific problems related to Sales and their details. I'm now getting a problem I haven't encountered before, and being completly new to Mongo doesn't help.
I've been using Robo 3t to help me in the task, and I haven't been able to get anywhere, having tried multiple solutions. I also can't seem to find the problem online, hence me asking here.
So, the code is as it follows:
db.salesdetails.aggregate(
[
{
$project: {
month: { $month: "$OrderDate" },
year: { $year: "$OrderDate" },
store:{$toInt:"$Store"},
ReceiptID:1,
_id:0
}
},
{
$match: {
month: 05,
year: 2011,
store:1046
}
}
])
The expected output would be the Store(an integer, as noted), the month, year and the ID of the Receipt that fall into the specificed timeframe and store.
However, instead of returning it, I get the following error:
https://i.imgur.com/NIYnelc.png
Once I remove the "store:1046" on the match field, the aggregation is sucessful, and I don't have any idea why it is behaving like this.
Thanks in advance.

The error shows you use MongoDB date operators ($month and $year in this case) on a string type. Do a db.salesdetails.findOne() and post the result. I believe you have a string value in OrderDate field instead of a date (ISODate(...)) I have verified on both Compass and Robo 3T that your aggregate pipeline work if the data type is correct.

Related

How to convert JavaScript Date into PostgreSQL Time (no timezone)?

I use knex with PosgreSQL. I have a table with a Time column.
After trying to insert data in the table, knex throws an error with the following message:
...invalid input syntax for type time: \"2021-07-21T14:40:00.000+03:00\..."
Code example
await knex('table_name')
.insert({ id: 1, time: new Date() })
What is a correct way to preserve JavaScript Date object as a PosgreSQL Time? Should I use 3rd party libs? Or it can be done using knex only?
I was able to fix this issue by manually converting the JavaScript Date object into one of the supported formats of the PostgreSQL.
The 8.5.1.1. Dates and 8.5.1.2. Times chapters have a full list of supported types.
My solution was to use date-fns/format (e.g. format(new Date(), 'HH:mm') // 14:00)
P.S. I'm not sure if this approach is right but it works.

Inserting numbers (floats) in Elasticsearch with the node client library

I'm trying to insert documents into Elasticsearch, they come as a format like:
{
total: 1,
subtotal: 1.2,
totalDiscount: 0}
The issue I'm having is with the zeroes, in JavaScript you can't force '0' to be represented as '0.0' or '0.00'.
I can't use text in the mappings in ES, as I want to obviously do mathematical operations on these fields. So I'm using a 'float' mapping for all of the above.
So, for each of those fields I have something like:
"subtotal": {
"type": "float"
},
I've tried all sort of different combinations, storing them as 'text' doesn't let me query them as I want, if I don't define the mapping I get a 'long' type for the fields, which truncates them, If I use float I get an exception mapper [totalDiscount] cannot be changed from type [float] to [long], if I remove them complitely, so skipping the save I get an error too
Rejecting mapping update to [...] as the final mapping would have more than 1 type
Any help much appreciated, thanks.
Update:
the scaled_float didn't work well for me, so I ended up doing this "the stripe way"
i.e. representing all monetary amounts in cents, safe, less space on disk, just works without having to define a mapping.
also used this https://currency.js.org/ to make sure the multiplication and output wouldn't suffer from the 'well known' issues with floats in JS.
as this might be useful to someone reading, I think the answer might be using this sort of mapping:
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
not only is more disk-efficient, but it won't have the above issues.
I'll keep this thread updated, to see if that works.
I am not familiar with the node client library, but in elasticsearch, the errors signify that -
mapper [totalDiscount] cannot be changed from type [float] to [long]
From the above error, it seems as if when you created the index, totalDiscount field, was defined with the float field data type and now you are changing it to the long data type. This is not possible, that is why the above error is thrown.
Rejecting mapping update to [...] as the final mapping would have more than 1 type
This error occurs because types are deprecated in APIs in 7.0, with breaking changes to the index creation, put mapping, get mapping, put template, get template and get field mappings APIs. Refer to this to know more about the removal of mapping types.

Mongoose only sorting dates by time

I am running a Node.JS server which uses Mongoose to query a MongoDB table that contains a date field. However, when I sort the results by date, they are actually only sorted by the time, disregarding the actual date. For example when I run the query
Competition.find({})
.sort('date')
.exec()
.then(data => {
res.json(data);
})
.catch(console.log);
It returns:
{"_id":"5c6c99e6e7179a27eb63a9a0","date":"2019-02-24T01:00:00.000Z","game_name":"UFO","status":"WAITING","comp_id":7},
{"_id":"5c6b95c8e7179a27eb62e7cf","date":"2019-02-19T06:41:47.185Z","game_name":"UFO","status":"COMPLETED","comp_id":6},
{"_id":"5c6b95b4e7179a27eb62e7cb","date":"2019-02-19T06:41:57.174Z","game_name":"UFO","status":"COMPLETED","comp_id":5},
{"_id":"5c6b95a4e7179a27eb62e7be","date":"2019-02-19T06:42:02.170Z","game_name":"UFO","status":"COMPLETED","comp_id":4},
{"_id":"5c6b9533e7179a27eb62e7a9","date":"2019-02-19T06:42:07.176Z","game_name":"UFO","status":"COMPLETED","comp_id":1},
{"_id":"5c6b958de7179a27eb62e7b8","date":"2019-02-21T18:48:50.497Z","game_name":"UFO_test","status":"COMPLETED","comp_id":3}
You can see here that the first entry has a date of 02-24 so it should show up last, but since the time is 1:00:00 it shows up before the other entries with the dates 02-19 and 02-21, since their times are later (06:41:47 for example).
The schema for the competition table is as follows:
const schema = new mongoose.Schema({
date: Date,
game_name: String,
status: String,
comp_id: Number,
});
I've tried to execute the date sort in a few different ways that Mongoose supports, but they all return the same results. If anyone could provide a fix or a workaround for this issue it would be greatly appreciated!
I had a similar problem and in my case, the dates were not saved as date in mongo like so:
"createdAt": {
"$date": "2018-04-25T22:48:06.863Z"
}
It could be related to the way you are creating your date object. Are you using moment or new Date() or anything else?

How to pass a DateTime from NodeJS Sequelize to MSSQL

I have a NodeJS project, and I am trying to pass an 'UpdateDate' field using Sequelize. I am receiving the error 'Conversion failed when converting date and/or time from character string'. I have tried passing a few different things:
Date.now()
new Date().toISOString()
Neither work. Am I missing something simple? I cannot change the column definition on the table. As far as I know, passing a string such as '2016-05-23 10:39:21.000' to a SQL DateTime field works in SSMS, but it seems to be an issue when using Sequelize and Node.
Thanks
Zach
This is caused by a known issue in Sequelize. The solution is to patch Sequelize's date to string format implementation, like explained here, so that all dates are handled properly. Below is the code that fixes the error.
const Sequelize = require('sequelize');
// Override timezone formatting for MSSQL
Sequelize.DATE.prototype._stringify = function _stringify(date, options) {
return this._applyTimezone(date, options).format('YYYY-MM-DD HH:mm:ss.SSS');
};
I figured this out, without changing the data type in the SQL database.
In my Model, I had my column defined as DataTypes.DATE, which, according to the Sequelize documentation, is the equivalent of a DateTime in SQL. However, this was throwing the error. When I changed the definition to DataTypes.STRING, and then added this:
var normalizedDate = new Date(Date.now()).toISOString();
normalizedDate now passes through to the DateTime column in SQL without a problem. The issue that I can tell, is Sequelize was adding a time zone to the Date before passing it. Such as, a date like:
'2017-11-01 16:00:49.349'
was being passed through as:
'2017-11-01 16:00:49.349 +00:00'
and it looks like SQL server does not like the '+00:00'.
I hope this helps others.
You can use this variable:
const timestamps = new Date() + 3600 * 1000 * 7;
I got the same issue. I was able to solve the issue by changing the model as follows.
ex:
create_at: {
type: 'TIMESTAMP',
defaultValue: new Date().toISOString(),
allowNull: false
},
update_at: {
type: 'TIMESTAMP',
defaultValue:new Date().toISOString(),
allowNull: false
}

Filter nested documents in meteorjs

I am having some trouble when trying to filter nested documents in Meteor, and I don't want to use MongoDB Aggregation to unwind my documents.
An example of my Users document
{
Publications:[{
type:1
},{
type:2
}]
}
When I do a find to get only type 1, I get the expected result - they return only the User documents who have a type 1 publication, but they also return the publications with type 2 too, because they are in the publications array of that User.
I can make a loop in the results to remove these publications manually before publishing, but I don't think this is the right approach.
Can someone please help guide me to a better solution?
Edited
The Sean answer is good but not the right yet, the projection dont work on meteor. That work on robomongo, but in the project still returning the 2 publications types of the user.
Give this query a shot.
Meteor.users.find(
{ 'Publications.type': 1 },
{ fields: { 'Publications.$': 1 } }
);
This should find users with publications of type 1 and will only include those matching publications in the output. You can include other fields in the output as well by including them in the projection parameter (e.g., { 'Publications.$': 1, profile: 1 }).
One thing to be aware of though. I think queries that use the { 'Publications.$': 1 } projection can only be done on the server side. The minimongo implementation used on the client does not support it.
More info about the $ projection can be found here.

Categories

Resources