MongoDB not returning empty objects in document - node.js

I've got this JSON snippet in a much much larger MongoDB document:
formConfig: {
person: {},
title: {name: 'title', ... },
name: {name: 'name', ...}
}
However, when I then try to retrieve the document containing this JSON it doesn't return person: {} at all. All I'm getting is:
formConfig: {
title: {name: 'title', ... },
name: {name: 'name', ...}
}
Which completely breaks the frontend side of things since I need to know that person is there, regardless if it's empty or not.
When I search for this issue I can't find any similar questions or resources explaining why this happens in the first place, let alone how I can fix it.
So how do I fix it so it returns the person as well?
Here's the actual query, appConfig contains the JSON as mentioned:
exports.getSingle = (req, res, next) => {
AppConfig.findOne({_id: req.params.id})
.exec((err, appConfig) => {
res.json({
error: null,
data: appConfig
});
}
);
};

The issue was actually at Schema level, not using minimize: false in the Schema options cause empty objects to be removed.
This works:
new Schema ({...}, {minimize: false});

Related

Can't acces specific values in my node.js mongoose Model (only the Object)

I have been working at this for the past 4 hours. I would therefore like some help. I want to access the specific values in my database, eg. as response.data.values.imglink although when adding imglink in console.log() I get undefined. I can get the general object but not the specifik values.
I have defined my Song Schema as:
const songSchema = new Schema({
values: [{
imglink: {
type: String
},
id: {
type: String
},
spotify: {
type: String,
},
soundCloud: {
type: String,
},
youtube: {
type: String,
},
appleMusic: {
type: String,
}}
],
}, {
timestamps: true,
})
As you can see values is an array of objects. People with a similiar problem on here hadn't included the correct values in their Schema, so maybe that's my problem? Although to me it looks correct. I then GET the values in my database. The JSON object usually looks something like this:
[
{
"_id": "5ffbba4dc47e847a79c9c68f",
"values": [
{
"_id": "5ffbba4dc47e847a79c9c690",
"imglink": "imagelink",
"id": "id",
"soundCloud": "soundcloudvalue",
"youtube": "youtubevalue",
"appleMusic": "applemusicvalue",
"spotify": "spotifyvalue"
}
]
}
]
I call it by this function, which is supposed to print out the individual values:
const getAllSongs = () => {
axios.get('http://localhost:5000/songs/'+id)
.then(function (response) {
console.log(response); // returns an object
console.log(response.data.values.imglink); // returns an object
})
.catch(function (error) {
// handle error
console.log(error);
})
}
I have an Express route object that allows me to access a song by it's id as GET http://localhost:5000/songs/id in the VS-code HTTP client (similiar to postman):
router.get(`/:id`, function(req, res) {
return Song.find(
{"values.id": req.params.id}
).then(function(song) {
// return orders when resolved
res.send(song);
console.log(id);
res.json('works yesss');
})
.catch(function (err) {
// handle error
res.status(400).json('Error: '+err)
})
});
Here are some popular solutions I have tried:
Wrapping response in JSON.stringify() doesn't work.
toObject() and toJSON() don't work either as they aren't defined when I use them.
the _doc hack doesn't work either.
I have tried looking at the Schema which is where I think the problem is. The POST-request adds the right data, the GET-request goes through I just can't acces the specific values.
I hope you have the time to help, thanks. I will be extremely grateful. And of course let me know if you have any questions.
the result of find() is a Array so to access the desired key, if length of result Array is one, to access the desired key is response.data[0].values[0].imglink.
note: the values key is a array of obejct
If the array size is more than one, you want to see the result, you can use map()
if it's not worked, using lean() like this
router.get(`/:id`, function(req, res) {
return Song.find(
{"values.id": req.params.id}
).lean().then(function(song) {
// return orders when resolved
res.send(song);
console.log(song[0].values[0].imglink); // type of song is array of object [] and values is array
res.json('works yesss');
})
.catch(function (err) {
// handle error
res.status(400).json('Error: '+err)
})
});

Check data exist or not when inserting multiple data in array with knex.js

For now, I insert the product first and insert multiple product tags in array.
But the product tags will be duplicate without validating the tag is existed or not.
How could I check tag is existed or not when I insert the tags?
Here is the code I used:
let product = {
product: {
name: 'techtech',
tagline: '描述',
thumbnail: 'images/products/techtech/thumbnail.png'
},
tags: [
{ name: 'Android', slug: 'android' },
{ name: 'MacOS', slug: 'macos' },
{ name: 'Windows', slug: 'windows' },
{ name: 'Linux', slug: 'linux' }
],
links: [ { url: 'techtech.cc' } ],
covers: [
{ url: 'images/products/techtech/cover_0.png', index: 0 },
{ url: 'images/products/techtech/cover_1.png', index: 1 }
]
}
// insert product
return db.transaction(trx => {
return trx('products')
.insert(product.product)
.returning('id')
// insert product_tags
.then(productIDs => {
return trx(productTags)
.insert(product.tags)
.returning('id')
// insert product_producttag_mapping
.then(productTagIDs => {
let productTags = productTagIDs.map((productTagID) => {
let productTag = {
product_id: productID,
producttag_id: productTagID
}
return productTag;
});
return trx('product_producttag_mapping')
.insert(productTags)
.returning('id')
})
})
Be careful, when you insert the product, your variable is productIDs, but you are creating productTag useing productId. You might want to add const productId = productIds[0].
When creating the productTag, you also need to use .id, like the following. Because knex is returning you objects with the property.
let productTag = {
product_id: productID.id,
producttag_id: productTagID.id
}
but to your actual question: What about making the tag name unique? This would give you a nice error on insert. Without transaction you could just ignore that error. Postgres and Mysql have a nice feature ON CONFLICT DO NOTHING. I am not sure if the databases would return the existing id when they detect a duplication. So I think you do not get around reading the existing tags. Find them by their name. With an index on that column, it should be reasonable fast.
pro tip: when rewriting your code using async/await, the small mistakes become more obvious and you can avoid the callback hell. You will less likely be tempted to avoid an extra query.

How to create a delete method in nodejs(express) with sequelize(sqlite) as database

I have been trying yesterday and still continuing today to figure out how to create a nodejs delete method so I can delete data from database based on ID.
I have tried different code from google/youtube/stackoverflow etc but nothing has worked so far.
The error I have with this code is that data.query is not a function. Data is a variable on my code.
If anyone has any idea how to fix please help.
app.js
app.delete('/zoom/:id', function(req, res) {
data.query('delete from', [req.params.id]);
res.render('deleted')
});
data.js
var Data = sequelize.define('data', {
subject: Sequelize.STRING,
MEETINGID: Sequelize.STRING,
Password: Sequelize.STRING
});
Sequelize destroy method seems like a suitable one. E.g.
app.delete("/zoom/:id", function (req, res) {
data.destroy({
where: {
// criteria
},
});
res.render("deleted");
});
To set a criteria which i suitable for your situation, you will need to take a look at sequelize syntax. I found some examples and may be you can modify them to your needs. Depending on your database structure.
where: {
'$car.id$': 2
},
where: {
furniture_type: 'leather'
},
where: {
id: {
$notLike: { $any: someValue }
}
},

NodeJS: How to get objects with variable child properties with MongoDB?

I am trying to get an array of documents where a child property is true. Here's some code:
public static getTeams(req, res) {
// Initialize a connection to the database
Globals.initDb(res).then((db: Db) => {
// Reference a collection in the Database
db.collection('teams', (error: Error, collection: Collection) => {
// Check if an error occured getting the collection
Globals.checkError({ error, result: collection, res }).then(() => {
// find teams that a user administrates
collection.find(
{ 'usergroups.users': { [req.params.id]: true } },
{ name: 1, icon: 1, type: 1, thumbnail: 1 }
).toArray((err, teams: Array<{ name: string, icon: string }>) => {
// make sure that went through OK
Globals.checkError({ error: err, result: teams, res }).then(() => {
if (!teams[0]) {
teams = [];
}
res.status(200).json(teams);
});
});
});
});
});
}
checkError is just a function I wrote to make it easier to check for errors, and it works fine, I checked it. I am trying to access an array of teams where the usergroups.users.#userId# is true. So if your id was j4k53, usergroups.users.j4k53 is true.
However, when it is true for multiple IDs, the documents are not returned. For example, if j4k53 and lfk3m are both true, it gets returned for neither of them.
Thank you for your help. (This is node with typescript, so it may look a little funky if you are not familiar with TS).
Got it: you can write it like this:
{ ['usergroups.users.' + req.params.id]: true}
Good luck to anyone who finds this useful!

Not able to persist array of objects in mongo using mongoose

I'm trying to persist an array of objects in a document using mongoose. I have tried multiple times but it's not persisting array in document. It places an empty array in document.
Following is my Schema:
var ProfileSchema = new Schema({
name: String,
PagesData: [{
pageAccessToken: {type: String, get: decryptText, set: encryptText},
category: String,
name: String,
id: String,
perms: [String]
}]
});
module.exports = mongoose.model('Profile', ProfileSchema);
I'm trying to save a document with an array of objects using following query:
var newProfile = new Profile();
newProfile.name = "someName";
newProfile.PagesData = [ { pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms:
[ 'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT' ] } ];
newProfile.save(function(err, result, numAffected){
if(err) {
console.log(err);
res.send(500, "Error");
}
console.log(result);
res.send(200, "Success");
});
I tried debugging the mongo commands using
require('mongoose').set('debug', true)
On Debug logs it shows, empty array during insert command execution.
Can anyone please tell me how can I store this array of object in my schema ?
Thanks,
Update:
It's been too long and I'm still not able to figure out the root cause of the problem. There is a long thread going on github for this.
https://github.com/Automattic/mongoose/issues/3249
I would like other experts to please take a look and suggest me some way by which I can solve the issue. I'm really stuck at this.
Update 2:
None of the solution worked for me so far, so I decided to modify the schema only to meet my requirements. This resulted in a different problem:
I want to create a map with a objectId as key and an array of string values as its value. The closest that I can get is:
var schema = new Schema({
map: [{myId: {type:mongoose.Schema.Types.ObjectId, ref: 'MyOtherCollection'}, values: [String]}]
});
But somehow this is not working for me. When I perform an update with {upsert: true}, it is not correctly populating the key: value in the map. In fact, I'm not even sure if I have declared the schema correctly.
Can anyone tell me if the schema is correct ? Also, How can I perform an update with {upsert: true} for this schema?
Also, if above is not correct and can;t be achieved then how can I model my requirement by some other way. My use case is I want to keep a list of values for a given objectId. I don't want any duplicates entries with same key, that's why picked map.
Please suggest if the approach is correct or should this be modelled some other way?
Thanks
I tried the exact code you have provided here and it's working for me. I am not sure what is causing the issue for you. Until and unless we get the same issue, it's very difficult to rectify it.
Here are few suggestions which you might try:
Create a simple schema and try storing the object, that way you can
figure it out if it has to do something with the schema.
You can try out your schema in a sample app to find if some
dependency is causing the problem.
Once you know where exactly the problem is, you would be able to figure out a solution too. I hope it helps.
I tested this and the insert works for me using the below:
(I had to remove the get: decryptText, set: encryptText)
var n = { name: "Testing for mongoose", PagesData : [{ pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms:
[ 'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT' ] } ] }
Profile.create(n, function (err) {
if (!err) {
return 'records saved successfully';
}
else {
return error on save:' + err;
}
});
To create multiple pageDatas you can use it as an embedded collection instead of using arrays.
The Schema will be as follows:
var PagesDataSchema = new Scheme({
pageAccessToken: {type: String, get: decryptText, set: encryptText},
category: String,
name: String,
id: String,
perms: [String]
})
var ProfileSchema = new Schema({
name: String,
PagesData: [PagesDataSchema]
});
module.exports = mongoose.model('Profile', ProfileSchema);
Reference: http://mongoosejs.com/docs/subdocs.html
For Saving the document you can use like.
exports.save = function(req,res){
var test = new ProfileSchema; // new object for ProfileSchema domain.
test.name= req.body.name;
if(req.body.PagesData){
req.body.PagesData.forEach(function(page){ // For every element of pageData from client.
test.PagesData.push(page) // This pushes each and every pagedata given from the client into PagesData.
})
}
test.save(function (saveErr, saved) { // Saves the new document into db.
if (saveErr) {
console.log(saveErr)
return;
}
res.status(HttpStatus.OK).json(saved);
});
};
Hope this helps.
Have you tried
Profile.create({
name: "someName",
PagesData: [
{
pageAccessToken: 'someToken',
category: 'Bags/Luggage',
name: 'someBrandName',
id: '12345',
perms: [
'ADMINISTER',
'EDIT_PROFILE',
'CREATE_CONTENT'
]
}
]
}, function(err, profile) {
// do your stuff
})
?

Resources