MongoDB: stored base64 buffer data and retrieved base64 does not match - node.js

I am posting small sized base64 encoded images (around 100-200K each) directly into mongodb using Mongoose. Before storing I could see the content is same as what sent from the client. But the query base64 string is not same as what went in? Any idea what I am missing ?
// process the add image request
app.post('/addimage', function(req, res) {
console.log("Addimage post....");
var qry = {'_email' : req.user.local.email, 'date' : req.body.date, 'subject' : req.body.subject };
Item.findOne(qry, function(err, item) {
if (err) {
console.log('Find images failed: ' + err);
var resp = '{"result" : "failed", "msg" : ' + err + ', "_req" : "addimage"}';
res.send(resp);
} else {
if (item == null) { // item doesn't exist, create now
var item = new Item();
item._email = req.body._email;
item.date = req.body.date;
item.subject = req.body.subject;
}
// add image
var image = new Image();
image.timestamp = req.body.timestamp;
image.contentType = req.body.contentType;
var imgBuf = new Buffer(req.body.image, 'base64');
image.image = imgBuf;
item.images.push(image);
item.save(function(err, result) {
if (err) {
console.log('Find images failed: ' + err);
var resp = '{"result" : "failed", "msg" : ' + err + ', "_req" : "addimage"}';
res.send(resp);
} else {
res.send('{"result" : "ok", _req: "addimage"}');
console.log("Image saved and responded to ...");
}
});
}
});
});
The data string stored in req.body.image started with something like "/9j/4AAQSkZJ ..." but from mongo shell I see it different. Is it the subtype 0 for the Bindata that's causing this ?
> db.items.find({subject:"Science"},{'images.image':1})
{ "_id" : ObjectId("547382943fc884447a767d58"), "images" : [ { "image" : BinData(0,"LwA5AGoALwA0AEEAQQBRAFMAawBaAEoAUgBnAEEAQgBBAFEAQQBBAEEAUQBBAEIAQQBBAEQALwA0AFEAQgBZAFIAWABoAHAAWgBnAEEAQQBUAFUAMABBAEsAZwBBAEEAQQBBAGcAQQBBAGcARQBTAEEAQQBN
Schema:
var imageSchema = new mongoose.Schema({
timestamp : String,
contentType : String,
image : Buffer,
}, { strict: true });
imageSchema.index({ timestamp: 1}, { unique: true });
var itemSchema = new mongoose.Schema({
_email : {
type: String,
required: true,
},
date : {
type: String,
required: true,
},
subject : {
type: String,
required: true,
},
images : [imageSchema],
}, { strict: false });
itemSchema.index({ _email: 1, date: 1, subject: 1}, { unique: true });
Mongodb version 2.6.5, Mongoose 3.8.1, Node v0.11.6-pre
Also, tried 'utf8' / 'ascii' / 'ucs2' instead of 'base64' while creating Buffer object.
Thanks!

It was node version ;( Restoring to 0.10.33 solved the issue !

Related

Casting error while saving in the database

I am using Angular as frontend and NodeJS for the backend.
I have a route that saves the data received from the frontend to the database. When I execute the save() method, I get prompted the following error:
err : ValidationError: conf.0: Cast to [Boolean] failed for value "[ {
name: 'v', percentage: 2, type: false, status: true } ]" (type string)
at path "conf.0"
Below is the route that stores the data:
app.post("/api/submitTaxCollection", (req, res) => {
console.log(req.body);
const submitTaxSchema = new addTaxesSchema(req.body);
try {
submitTaxSchema.save(function (err) {
if (err) return console.log("err : " + err);
});
} catch (error) {
console.log("ERROR : " + error);
return res.send(error);
}
});
and this is the schema.ts file:
var mongoose = require("mongoose");
//Define a schema
var taxSchema = mongoose.Schema;
var AddTaxSchema = new taxSchema({
parentId: String,
conf: [
{
name: String,
percentage: Number,
type: Boolean,
status: Boolean,
},
],
});
var newTaxesSchema = mongoose.model("addTaxSchema", AddTaxSchema);
module.exports = newTaxesSchema;
In Angular, model is setup as below:
export class TaxRatesConfigurationsModel {
name: string = "";
percentage: number = 0;
type: boolean = false;
status: boolean = true;
}
export class TaxRatesModel {
parentId: string = "";
conf: TaxRatesConfigurationsModel[] = [];
}
and I am calling the API as below:
this._httpService
.post(environment.url + "/api/submitTaxCollection", request)
.subscribe((data) => {
console.log(data);
});
when I console.log(req.body);, I get the following printed to the console (Nodejs):
{
parentId: '23948923nur8cw9yicnyu',
conf: [ { name: 'v', percentage: 2, type: false, status: true } ]
}
and the error occurs in Nodejs
What is causing this weird issue?

Function not returning anything in nodejs

I am creating a web app's backend , where different posts are stored and their categories are also stored. Since each category has its own properties (like description , color etc. ) , I've created a new category schema and storing the category reference in the article.
Here's my post route:
Code_1
Code_2
// CREATE ROUTE : adding New Article
app.post("/addnew", upload.single('image'), function(req,res){
//get data from form and add to news array
var title = req.body.title;
var image = req.body.image
if (req.file){
var imgURL = req.file.path;
}
var description = req.body.description;
var category = req.body.category;
var tag = req.body.tag;
// Handling the category entered by user
function checkCategory(name , color, totalArticles, desc){Category.find({name: category}, (err, foundCategory) => {
if(err){
console.log(err)
} else {
console.log("found category in starting of checkCategory function : " , foundCategory)
if (foundCategory[0]){
console.log("Category" + foundCategory + "already exists...")
return foundCategory
} else {
// var name = req.body.name
// var color = req.body.color
// var totalArticles = req.body.totalArticles
// var desc = req.body.desc
var category = {name: name , color : color , totalArticles: totalArticles || 0 , desc : desc }
Category.create(category, (err, newCategory) => {
if (err){
console.log(err)
} else {
console.log("New category Created : " , newCategory)
// category = newCategory
return newCategory
}
})
}
}
})
}
console.log("??????????????? category returned", category)
var nyaArticle= {title: title, imgURL: imgURL, description: description};
// create a new Article and save to db
Article.create(nyaArticle,function(err,newArticle){
if(err){
console.log(err);
} else {
// redirect back to main page
console.log("new article created")
console.log(newArticle)
category = checkCategory(req.body.name, req.body.color, req.body.totalArticles, req.body.desc)
console.log("checkCategory Returned :::::" , category)
newArticle.category.push(category)
newArticle.save()
res.redirect("/");
}
})
The function checkCategory checks if the category already exists or else it will create a new one .
But according to these logs , my function is not returning the category created , however the category is successfully created in DB and also can be seen in Logs
Articles App has started on port 3000
DB Connected...: cluster0-shard-00-00-ktzf1.mongodb.net
??????????????? category returned undefined
new article created
{
category: [],
hits: 0,
tag: [],
comments: [],
_id: 60be0fe92a8b88a8fcea71dc,
title: 'TESTING',
description: 'TESTING',
created: 2021-06-07T12:24:09.563Z,
__v: 0
}
checkCategory Returned ::::: undefined
found category in starting of checkCategory function : []
New category Created : {
totalArticles: 444,
_id: 60be0fea2a8b88a8fcea71dd,
name: 'TESTING',
color: 'RED ALERT',
desc: 'THiS TESTING',
__v: 0
}
due to this null is getting stored in my category in
DB
Am I using the right approach or should I follow some other approach, any help is much welcomed.
The categorySchema looks like this :
var categorySchema = new mongoose.Schema({ name: String, color: String, totalArticles: { type:Number, default: 0 }, desc : String });
ArticleSchema:
var newSchema = new mongoose.Schema({
title: String,
imgURL: String, //{type: String, default: "https://source.unsplash.com/1600x1080/?news"},
description: String,
// category: String,
category: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Category"
}
],
hits : {
type: Number ,
default : 0
},
tag: [
{type: String}
],
created: {type: Date, default: Date.now},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
You are assigning var category inside the callback function returned from your checkCategory, and that var is only available inside that callback.
Besides, you code have several other problems, like Category.find({name: category}) which will never return anything. (it should be {name:name}).
In general, you'll be much better off using async\await, (coupled with a try\catch, if you like):
async function checkCategory(name, color, totalArticles, desc) {
try {
let category = await Category.findOne({ name });
if (category) {
console.log(`Category ${category.name} already exists...`);
return category;
}
else {
let newCategory = await Category.create({ name: name, color: color, totalArticles: totalArticles || 0, desc: desc });
console.log("New category Created : ", newCategory);
return newCategory;
}
} catch (error) {
console.log(err)
}
}
And in your router function:
app.post("/addnew", upload.single('image'), async function(req,res){
let {name, color, totalArticles, desc} = req.body;
let category = await checkCategory(name, color, totalArticles, desc);
let newArticle = await Article.create({ title: title, imgURL: imgURL, description: description, category: [category] });
res.redirect("/");
}

How to create new record through JSON Data

Here, I have some difficulty to how to create new record whenever i have create one csv file and upload it,
then now how can i create new record throgh this,
please help me.!
This is my Csv file.
name,companyId,engineId,colorId
car1,123,123,123
car2,456,456,456
uploadAvatar: function (req, res) {
let fileInputName = 'assets/excel/carData.csv';
let fileOutputName = 'myOutputFile.json';
req.file('excel').upload({
// don't allow the total upload size to exceed ~10MB
dirname: require('path').resolve(sails.config.appPath, './assets/excel'),
saveAs: 'carData.csv',
maxBytes: 10000000
}, function whenDone(err, uploadedFiles) {
if (err) {
return res.serverError(err);
}
// If no files were uploaded, respond with an error.
if (uploadedFiles.length === 0) {
return res.badRequest('No file was uploaded');
}
csvToJson.generateJsonFileFromCsv(fileInputName, fileOutputName);
csvToJson.fieldDelimiter(',') .getJsonFromCsv(fileInputName);
let json = csvToJson.getJsonFromCsv("assets/excel/carData.csv");
csvToJson.formatValueByType().getJsonFromCsv(fileInputName);
//var result = [];
var name = "";
var comapanyId = "";
var engineId = "";
var colorId = "";
for (let i = 0; i < json.length; i++) {
console.log(json[i]);
**// How to create new record ?**
}
return res.json({
message: uploadedFiles.length + ' file(s) uploaded successfully!',
});
});
},
This is my model file
module.exports = {
tableName: 'Car',
schema: true,
attributes: {
name: {
type: 'STRING'
},
companyId: {
model: 'Master',
columnName: 'companyId'
},
engineId: {
model: 'Master',
columnName: 'engineId'
},
colorId: {
model: 'Master',
columnName: 'colorId'
},
car: {
collection: 'Order',
via: 'carId'
},
},
};
You have to call the .createEach([cars]) method.

Schema validate causes Save to fail in Mongoose

Why does the following code causes the Mongoose save to fail? If I remove validate: utils.uuid.isValid (returns a boolean) the process will complete:
var accountSchema = new mongoose.Schema({
_id : { type: String, default: utils.uuid.init, validate: utils.uuid.isValid },
n : { type: String }, // Display Name
ac : { type: Date },
au : { type: Date },
ad : { type: Date },
am : { type: String }
});
Also, if I remove the validate property of the field, and try setting values in the pre('validate', cb) or pre('save', cb) call, this will cause the same result:
accountSchema.pre('validate', function(next) {
var now = new Date(),
memberId = this.am;
console.log('In Account validate (member : ' + memberId + ')');
if (this.isNew) { this.ac = now; console.log('Item is new.'); }
else if (this.isModified()) { this.au = now; console.log('Item is modified.'); }
else { return next();
console.log('Canceling Account validate.');
}
console.log(JSON.stringify(this));
console.log('Completed Account validate.');
next();
});
Nothing crashes. In Webstorm, processing just stops with a message "Process finished with exit code 139".

Populate with inherited document in Mongoose

I am trying to create a database schema for the following model:
I am not sure what the better way to represent this in a MongoDb would be, but since I am using Mongoose and there is a plugin for inheritance, I am trying the following:
var mongoose = require('mongoose')
, extend = require('mongoose-schema-extend')
, Schema = mongoose.Schema
, ObjectId = mongoose.Schema.Types.ObjectId
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
//Mashup and Item are bound (itemSchema is a sub-doc)
var itemSchema = new Schema({
pos: { top: Number, left: Number }
, size: { width: Number, height: Number }
, component: { type: ObjectId, ref: 'Component' }
})
var mashupSchema = new Schema({
name: String
, desc: String
, size: { width: Number, height: Number }
, items: [itemSchema]
})
var componentSchema = new Schema({
name: String
, desc: String
}, { discriminatorKey : '_type' })
var imageComponentSchema = componentSchema.extend({
url: String
})
var textComponentSchema = componentSchema.extend({
text: String
})
var htmlComponentSchema = componentSchema.extend({
html: String
})
var webComponentSchema = componentSchema.extend({
page: { type: ObjectId, ref: 'Page' }
, selector: { type: ObjectId, ref: 'Selector' }
})
var pageSchema = new Schema({
name: String
, desc: String
, url: String
, active: { type: Boolean, default: false }
, webComponents: [{ type: ObjectId, ref: 'WebComponent' }]
})
var selectorSchema = new Schema({
desc: String
, url: String
, cssPath: String
})
///MODELS
var Mashup = db.model("Mashup", mashupSchema)
var Component = db.model("Component", componentSchema)
var ImageComponent = db.model("ImageComponent", imageComponentSchema)
var TextComponent = db.model("TextComponent", textComponentSchema)
var HtmlComponent = db.model("HtmlComponent", htmlComponentSchema)
var WebComponent = db.model("WebComponent", webComponentSchema)
var Page = db.model("Page", pageSchema)
var Selector = db.model("Selector", selectorSchema)
//CREATE
//a new empty mashup
//var aMashup = new Mashup({ name: "Test" });
Mashup.create({ name: "Test" }, function (err, mashup) {
if (err) return
console.log("Saved: empty mashup")
//mashup saved, create a webComponent
var aWebComponent = new WebComponent({ name: "Map", desc: "A map" })
//create a page
var aPage = new Page({ name: "Maps", desc: "Google Maps", url: "http://maps.google.com" })
aPage.webComponents.push(aWebComponent)
aWebComponent.page = aPage
//create a selector
var aSelector = new Selector({desc: "Just the map", url: "maps.google.com", cssPath: "#map" })
aWebComponent.selector = aSelector
//save the component
aWebComponent.save(function(err) {
if (err) return
console.log("Saved: WebComponent")
aPage.save(function(err) {
if (err) return
console.log("Saved: the Page")
aSelector.save(function(err) {
if (err) return
console.log("Saved: the Selector")
//finally add the item with the new component
var item = { pos: { top:6, left:10 }, size: { width:100, height:100}, component: aWebComponent }
mashup.items.push(item)
mashup.save(function (err) {
if (err) return
console.log("Saved: mashup with item (WebComponent with Page and Selector)")
//POPULATE
Mashup
.find({})
.populate("items.component")
.exec(function (err, mashup) {
if (err) console.log(err)
console.log(mashup);
})
})
})
})
})
})
});
This is a use case scenario, where a user creates a Mashup and then adds a new Item to it by creating a new WebComponent. I need that Item class because each different mashup should be able to have "instances" (i.e. the Items) of existing Components.
Now, I am new to Mongoose and I am sure things could be done differently. Any suggestion here is welcome. However, when I try to query the Mashups populating the results, the output I get is:
Saved: empty mashup
Saved: WebComponent
Saved: the Page
Saved: the Selector
Saved: mashup with item (WebComponent with Page and Selector)
[ { __v: 1,
_id: 520a8aae3c1052f723000002,
name: 'Test',
items:
[ { component: null,
_id: 520a8aaf3c1052f723000006,
size: [Object],
pos: [Object] } ],
size: {} } ]
component should be populated but it is not. I guess this is because it expects a Componentwhile it gets a WebComponent. How do I fix this? Should I stop trying with inheritance? What other ways are there to create a DB schema for this model?
Doh.. changing
var componentSchema = new Schema({
name: String
, desc: String
}, { discriminatorKey : '_type' })
to
var componentSchema = new Schema({
name: String
, desc: String
}, { collection : 'components', discriminatorKey : '_type' })
Fixes the issue. Not sure why.

Resources