Unknown bson type DECIMAL128 in when show on template client? - mongodb

I user find for meteor and aggregate I try to get data form server I test both of them it work but, I get trouble when I use
.toNumber() function with aggregate that data type amount is Decimal in mongodb. I am not sure to get data to show on client in template. any suggestion Please help me
My Code collection Schema
Collection schema (SimpleSchema)
amount: {
type: Object, // I tried use `Decimal`
blackbox: true,
},
Method on server sample it work find after insert amount store in data type Decimal and get data both with findOne abd aggregate
import { Decimal } from 'meteor/mongo-decimal'
Meteor.methods({
insert(){
return Collection.insert({amount: Decimal(0.123)})
},
findOne(){
return Collection.findOne({})
},
aggregate(){
return Collection.aggregate([{ $limit: 1 }])[0] // sakulstra:aggregate
}
})
Get data in Client when get with findOne .toNumber() it work fine but when I use with aggregate .toNumber() it unknown.
So during find query I am getting Unknown bson type DECIMAL128
Meteor.call('findOne', (err, res)=>{
res.amount.toNumber() // Work fine with Decimal JS method
})
Meteor.call('aggregate', (err, res)=>{
res.amount.toNumber() // don't work with Decimal JS method
})

Related

mongoose .skip() based on parameter value

I'm trying to implement pagination with mongoose for a mongoDB collection.
The console.log(req.params.start); correctly outputs the start value. However, the query does not start at this value — it starts from the beginning, regardless of the value.
If I change req.params.start to a non variable number, 2, for example — it correctly skips 2 records.
sampleRoute.route('/collection/:start').get((req, res) => {
console.log(req.params.start);
MyModel.find()
.skip(req.params.start)
.limit(2)
.exec(function (err, doc) {
if(err) { res.status(500).json(err); return; };
res.status(200).json(doc);
});
})
How can I successfully skip using a variable? Thank you.
As req.params.start is passed as a string, I needed to convert it to Number:
.skip(Number(req.params.start))

Suppress value types in MongoDB Stitch function

A Stitch function returns value types for each non-string field. I believe this is because functions return data in MongoDB Extended JSON.
The Mongo Shell, on the other hand, returns standard JSON, and no value types.
How do I suppress value types returned by a MongoDB function? Is it possible to convert EJSON back to JSON?
For a date field, for example, the Mongo Shell returns:
"dob" : ISODate("1995-01-11T00:00:00.000-07:00")
The same query in a Stitch function returns:
"dob": {
"$date": {
"$numberLong": "232182000000"
}
My Stitch function looks like this:
exports = function(){
const collection = context.services.get("mongodb-atlas").db("mydb").collection("mycollection");
const doc = collection.find().toArray();
return doc;
};
Is there a helper function that can strip out the value types? Something like...
exports = function(){
const collection = context.services.get("mongodb-atlas").db("mydb").collection("mycollection");
const doc = collection.find().toArray();
const noValueTypes = doc.stripValueTypes()
return noValueTypes;
};
When a Function result is passed to the client, it is indeed serialized as EJSON.
Ideally, your client can parse EJSON back into regular JS objects, e.g. with the EJSON library, which is also built into the Stitch SDK.
Of course, if you are using the Stitch SDK, calling the function directly is even better.
Another option is to use the response object to pass JSON, like so:
exports = function(request, response) {
// ... get data ...
response.addHeader(
"Content-Type",
"application/json"
);
response.setBody(JSON.stringify(myData));
};
Note that JSON can't represent some special BSON types, such as object id, so you will want to keep this in mind when deciding what data to return.

How to split up Postgres data into JSON/object, or an easily usable format for Express

I'm using pg-promise to facilitate requests between Express and a Postgres database.
Using pg-promise's any:
db.any('select * from blog')
.then(function (data) {
console.log(data);
})
.catch(function (error) {
console.log('ERROR:', error);
});
There is only one row in the Postgres table, so the query above gets a block of data from Postgres that, when output to the terminal, looks like this:
[ { id: 1,
date: '2018-12-17',
title: 'Here is a Title',
article: "Okay, there's not much here yet.",
img1: null,
img2: null,
img3: null,
keywords: 'news' } ]
In an effort to break up this data into usable bits that I can then assign to values in Express, I attempted to use JSON.parse() on this data. I really didn't know what to expect from doing this.
db.any('select * from blog')
.then(function (data) {
data = JSON.parse(data); // attempting to parse the Postgres data
console.log(data);
})
An error occurred:
ERROR: SyntaxError: Unexpected token o in JSON at position 1
I also tried to call on this data as if it were an object.
db.any('select * from blog')
.then(function (data) {
console.log(data);
console.log(data.id); // attempting to get just the id from the data
})
Which output to the terminal as:
undefined
How can I use this data within a js environment like Express? Not sure if it makes a difference, but I'm trying to use Pug to template everything to the front-end.
The select query returns array of objects with each element in the array corresponding to a row in the table (blog) in your case and each key in the object corresponding to the table column.
I am not sure why you are trying to JSON-parse it, as JSON expects an object, and it cannot parse arrays.
Try JSON.parse(JSON.stringify(data));

How to send ISODate in meteor.call method

I am creating an array of objects in client side in the meteor, and each object have modified date inside it as mentioned below:
Client Side:
student;
here student is an array of an object contains name, id, roll_no
var array = [];
student.forEach(function(singleStud, index){
var single_obj ={
"name":singleStud.name,
"student_id":singleStud.id,
"roll_no":singleStud.roll_no,
"college_name":"ABC college",
"college_id":"xyz Id",
"created_date": new Date()
}
array.push(single_obj);
},this)
Meteor.call('saveDetails', array, function (error, result) {
console.log("data Saved Successfully");
});
Server Side:
I have used plugin mikowals:batch-insert to insert an array which is equivalent to insertMany in mongo.
Meteor.methods({
"saveDetails": function (array) {
try {
studentDetails.batchInsert(array);
return true;
} catch (err) {
return err;
}
}
});
when I save it the created_date is saving it as a string ("2018-04-23T10:26:26.766Z"), but I want it to be saved it as a date data type (ISODate("2018-04-23T10:26:26.766Z")).
How can I achieve from the client side in meteor.call ???
This is actually a bug in mikowals:batch-insert. mikowals-batch-insert recursively attempts to convert objects into a JSON format friendly with MongoDB. As part of this process, it uses underscore clone to make shallow copies of primitive types. While Date is a primitive, it cannot be cloned with _.clone, so it mutates your date to a string (eww). You should open an issue with mikowals:batch-insert.
Regardless, you shouldn't be defining this data on the client. The client could maliciously inject false information (which could break your application's logic). Instead, you should map over the input and inject the date into incoming objects.

Meteor-Mongo: Error handling for findone

I am trying to handle errors using findOne in meteor-mongo.
From this stackoverflow question, it appears that I should be able to handle errors by doing collection.findOne({query}, function(err, result){ <handleError> }, but doing so results in an errormessage:
"Match error: Failed Match.OneOf, Match.Maybe or Match.Optional validation"
The following code works:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}),
};
}, App);
The following code does not:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}, function(err,result){
if(!result){
return {}
};
}),
};
}, App);
What am I doing wrong and how should I be resolving this error? Is this a meteor specific error?
Any help is greatly appreciated!
What kind of error are you exactly trying to handle with your callback?
Meteor's findOne is different from node's mongodb driver's findOne that the post you link to uses.
The expected signature is:
collection.findOne([selector], [options])
There is no callback involved, since the method runs synchronously (but is reactive).
If you want to return a default value when the document is not found, you can simply use a JS logical OR:
// Provide an alternative value on the right that will be used
// if the left one is falsy.
theData.findOne({_id: theID}) || {};
A more rigorous approach would be to compare its type with
typeof queryResult === 'undefined'
Note that if theData collection is fed by the above subscription Meteor.subscribe('thePubSub'), I doubt Meteor will have time to populate the collection on the client by the time you query it…