node js mongoose find data from array in collection - javascript

I am working with node.js and mongoose I am stuck in a problem. My users collection looks like.
{
"_id": ObjectId("564b6deec50de8d827c0a51a"),
"email": "ak#gmail.com",
"ngos": [
{
"_id": ObjectId("564b7527ecc479e4259edff7"),
"name": "Children trust",
},
{
"_id": ObjectId("564b79e0ecc479e4259edff8"),
"name": "Charity Two",
"location": "Australia"
}
]
}
{
"_id": ObjectId("564e0a18c8cd4b5420a9250c"),
"email": "some#gsomel.com",
"ngos": [
{
"_id": ObjectId("564e0b3bc8cd4b5420a92510"),
"name": "Charity Two",
"location": "US"
}
]
}
I want to find all the ngos whose name is like Charity so it should return me.
{
"_id": ObjectId("564e0b3bc8cd4b5420a92510"),
"name": "Charity Two",
"location": "US"
}
{
"_id": ObjectId("564e0b3bc8cd4b5420a92510"),
"name": "Charity Two",
"location": "Australia"
}
I tried
User.find({"ngos.name": new RegExp(name, 'i')}, function(err, user) {
if (err) return next(err);
res.json(user);
});
It gave me both users with all the data as I am returning the user but if I change res.json(user); to res.json(user.ngos); I am not getting any response.
How can I retreive those particular ngos whose name matches?
Thanks

Use regex filtering on your final result array as follows:
var rgx = new RegExp(name, 'i');
User.find({"ngos.name": rgx})
.lean()
.exec(function(err, users) {
if (err) return next(err);
var result = users.map(function (n){
return n.ngos.filter(function(val){return rgx.test(val.name);});
})
console.log(JSON.stringify(result, undefined, 4));
res.json(result);
});
Check the demo below.
var cursor = [
{
"ngos": [
{
"_id": "564b7527ecc479e4259edff7",
"name": "Children trust",
},
{
"_id": "564b79e0ecc479e4259edff8",
"name": "Charity One",
"location": "Australia"
}
]
},
{
"ngos": [
{
"_id": "564e0b3bc8cd4b5420a92510",
"name": "Charity Two",
"location": "US"
}
]
}
];
var rgx = new RegExp('Charity', 'i');
var result = cursor.map(function (n){
return n.ngos.filter(function(val){return rgx.test(val.name);});
})
pre.innerHTML = "result: " + JSON.stringify(result, null, 4);
<pre id="pre"></pre>

Hope this helps,
User.find({"ngos.name": new Regex(name, 'i')},{'ngos':1}).exec(function(err,data){
if (err) throw(err);
res.json(data);
});

just try this way in mongoose
you getting res is Array so use "forEach"
User.find({'ngos.name':new RegExp('name', 'i')}, {'ngos':1},function(err,users){
users.forEach( function(user) {
user.ngos.forEach( function(nom) {
console.log( nom );
})
} );
})
just try this way in mongodb
db.user.find({'ngos.name':new RegExp('name', 'i')},{'ngos':1}).forEach( function(user) {
user.ngos.forEach( function(nom) {
print( nom );
})
} )
I think this help to u !

Related

MongoDB refuses to insert data

I have been trying to insert a piece of data in my db collection, mys chema looks like this
{
"_id": {
"$oid": "62d30157607575f6be6ce948"
},
"semester": "sem-5",
"subjectData": {
"subjectName": "eco",
"questionBank": [{
"question": "who are",
"answer": {
"introduction": "Hello my name is Izaan",
"features": ["tall", "handsome"],
"kinds": ["very", "kind"],
"conclusion": "Mighty man",
"_id": {
"$oid": "62d30157607575f6be6ce94b"
}
},
"_id": {
"$oid": "62d30157607575f6be6ce94a"
}
}],
"_id": {
"$oid": "62d30157607575f6be6ce949"
}
},
"__v": {
"$numberInt": "0"
}
}
And I would like to insert some questions and answers depending on semester and subject, first I want to query for the semester and then subject and then insert data without deleting prev data in the questionBank array
Here is how I am doing this and which is giving all kinds of error and still I have not managed to get the desired result
// IF DATA EXISTS UPDATE QUESTIONSBANK WITHOUT DELETING ANY ITEMS
try {
const result = await semesterData.update({
semester: {
$eq: semesterRecieved
},
subjectName: {
$eq: subject
},
}, {
$push: {
question: questionRecieved,
answer: answerRecieved2,
},
}, );
res.send(result);
} catch (error) {
console.log(error);
res.status(404).send(error.message);
}
}

Filter an nested Object with filter and map with JavaScript

I know that this is close to a duplicate but I can't get the code to work. I have an object that I need to filter and I'm currently trying to emulate the accepted as an answer the code at Javascript filtering nested arrays
My data object is:
[{
"project_num": "5R01DA012513-23",
"principal_investigators": [{
"profile_id": 2076451,
"full_name": "PK",
"title": ""
}]
},
{
"project_num": "5R01DK118529-03",
"principal_investigators": [{
"profile_id": 8590844,
"full_name": "HW",
"title": "PROFESSOR, SCIENTIFIC DIRECTOR"
}]
},
{
"project_num": "3R01AA025365-05S1",
"principal_investigators": [{
"profile_id": 8730036,
"full_name": "JJ",
"title": "ASSOCIATE PROFESSOR OF PSYCHIATRY"
}]
},
{
"project_num": "1R01HL163963-01",
"principal_investigators": [{
"profile_id": 2084037,
"full_name": "KH",
"title": "ASSOCIATE PROFESSOR"
},
{
"profile_id": 11309656,
"full_name": "AM",
"title": "RESEARCH ASSISTANT PROFESSOR"
}
]
},
{
"project_num": "5R25HL092611-15",
"principal_investigators": [{
"profile_id": 1886512,
"full_name": "CW",
"title": "P"
}]
}
]
and my JavaScript code is:
let payLoad = 1886512
const result = this.reporterData.map(t => {
const principal_investigators = t.principal_investigators.filter(d =>
d.profile_id === payLoad);
return { ...t,
principal_investigators
};
})
I need to pass in a profile_id as a payload and return the objects that will fill a data table.
The data can be 1000's of items and the principla_investigators can be multiple entries. When I use the code that I have it return all of the objects. Can someone point out my error? Thanks
You can try doing like this:
const result = this.reporterData.filter((t) => {
const principal_investigators = t.principal_investigators.filter((d) => d.profile_id === payLoad)
return (principal_investigators.length > 0)
})
I understand that you want an array with all the investigators matching that ID, right?
Try this:
const result = this.reporterData.reduce((previous, current) => {
if (current.principal_investigators) {
current.principal_investigators.forEach(pi => {
if (pi.profile_id === payLoad) {
previous.push(current)
}
});
}
return previous
}, [])
You can also do for loops with the same result:
const result = [];
for (project of this.reporterData) {
if (project.principal_investigators) {
for (pi of project.principal_investigators) {
if (pi.profile_id == payLoad) {
result.push(pi);
}
}
}
}

Update multiple or single object in an array with specified data from request

I am not great with MongoDB's advanced techniques.
My record in the MongoDB collection:
{
"_id": ObjectId("1"),
"manager": ObjectId("12345"),
"code": "PS",
"title": "Performance System",
"users": [
{
"_user": ObjectId("1"),
"role": "Member",
},
{
"_user": ObjectId("2"),
"role": "Member",
},
{
"_user": ObjectId("3"),
"role": "Member",
}
],
}
Node.js / ExpressJS
I created API to update the array like below but did not work.
const updateProjectMember = asyncHandler(async (req, res) => {
const { userID, role } = req.body.userData;
try {
const project = await Project.updateMany(
{ _id: req.params.projectID },
{ $set: { "users.$[selectedUser].role": role } },
{ arrayFilters: { "selectedUser._user": { $in: userID } } }
);
res.status(200).json(project);
} catch (error) {
res.status(400);
throw new Error(error);
}
I use the API parameter to get the project ID. Here is the request body data:
{
userID : ["2","3"];
role: "Admin"
}
So the API will get an array of userID to match and set all "role" fields to "Admin" to all matched.
I wanted the data to be like this:
{
"_id": ObjectId("1"),
"manager": ObjectId("12345"),
"code": "PS",
"title": "Performance System",
"users": [
{
"_user": ObjectId("1"),
"role": "Member",
},
{
"_user": ObjectId("2"),
"role": "Admin",
},
{
"_user": ObjectId("3"),
"role": "Admin",
}
],
}
Am I doing the right practice? If it is bad practice, what is the best way to solve this?
The query is fine. Just make sure that you pass the value with the exact type as in the MongoDB document.
var mongoose = require('mongoose');
const updateProjectMember = asyncHandler(async (req, res) => {
const { userID, role } = req.body.userData;
userID = userID.map(x => mongoose.Types.ObjectId(x));
try {
const project = await Project.updateMany(
{ _id: mongoose.Types.ObjectId(req.params.projectID) },
{ $set: { "users.$[selectedUser].role": role } },
{ arrayFilters: { "selectedUser._user": { $in: userID } } }
);
res.status(200).json(project);
} catch (error) {
res.status(400);
throw new Error(error);
}
}

How to do nested loops with object jSON data on nodejs

I'm new use nodejs and mongodb, now I build restful API use nodejs and mongodb. I want use response standard for my API with http://jsonapi.org standard.
I need a suggestion from advance how best way to do it, making my API response like the following JSON data:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/users"
},
"data": [{
"type": "users",
"id": 5b647bb8998248235a0aab3c,
"attributes": {
"username": "luke",
"email": "luke#mail.com",
"password": "password",
"hashpassword":"",
"oldpassword":"$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
"salt":"2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
"usertype":"bisnis",
"userstatus":"not aktif"
}
}, {
"type": "users",
"id": 5b647bdf998248235a0aab3d,
"attributes": {
"username": "ken",
"email": "ken#mail.com",
"password": "password",
"hashpassword":"",
"oldpassword":"$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
"salt":"2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
"usertype":"bisnis",
"userstatus":"not aktif"
}
}]
}
I have problem with nest iteration when create output as above. This my code:
const UsersModel = mongoose.model('Users');
//...show list user
exports.listUsers = (req, res) => {
UsersModel.find({}, (err, result) => {
if (err) {
res.send({code: 400, failed: 'Error 400'});
}
res.json(result);
});
};
And this is my result JSON:
[
{
"type": "users",
"userstatus": "not aktif",
"_id": "5b647bb8998248235a0aab3c",
"username": "luke",
"email": "luke#mail.com",
"password": "password",
"usertype": "bisnis",
"hashpassword": "$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
"salt": "2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
"__v": 0
},
{
"type": "users",
"userstatus": "tidak aktif",
"_id": "5b647bdf998248235a0aab3d",
"username": "ken",
"email": "ken#mail.com",
"password": "password",
"usertype": "personal",
"hashpassword": "$2a$10$hok988mszyIBiXVNjmfifOiPNzXkBRRRynXJS/0qCkvlaBOQs65MO",
"salt": "IiMvtVYVqTpZFXmYQIM4IlS6PJFVZ3kw",
"__v": 0
}
]
And this is my temporary code for my problem.
//...show list user
exports.listUsers = (req, res) => {
UsersModel.find({}, (err, result) => {
if (err) {
res.send({code: 400, failed: 'Error 400'});
}
let listData = [];
for (let key in result) {
let data = {};
let attr = {};
if (result.hasOwnProperty(key)) {
data.type = result[key].type;
data.id = result[key]._id;
for(let i in result[key]) {
if(result[key].hasOwnProperty(i)) {
attr.username = result[key].username;
attr.email = result[key].email;
attr.password = result[key].password;
attr.hashpassword = result[key].hashpassword;
attr.oldpassword = result[key].oldpassword;
attr.salt = result[key].salt;
attr.usertype = result[key].usertype;
attr.userstatus = result[key].userstatus;
}
}
data.attribute = attr;
listData.push(data);
}
}
let collections = {
"meta": {
"copyright": "Copyright 2018 Kotakku Studio and Lab",
"authors": [
"sw. saputra"
]
},
"link": {
"self": req.protocol + '://' + req.get('host') + req.originalUrl
},
"data": listData
}
res.json(collections);
});
};
Please give me suggestion the elegant and the best way to solve my problem if my temporary code is not correct.
Thanks advance.
You need to create a proper mongoose schema according to your requirement and map the res to the schema.
//Schema for users
var UsersSchema = mongoose.Schema({
links: {
self: String
},
data:[{
type: String,
attributes: {
username: String,
.
.
.
}
}]
})
id for each document in an array will be created automatically by MongoDB.
For mongoose schema docs see http://mongoosejs.com/docs/guide.html
You can also check this simple TODO API for reference https://github.com/mkujaggi/node-course-todo-api
In this condition's statement:
if(result[key].hasOwnProperty(i)) {
You should be accessing the i of result[key]:
if(result[key].hasOwnProperty(i)) {
attr.username = result[key][i].username;
attr.email = result[key][i].email;
attr.password = result[key][i].password;
attr.hashpassword = result[key][i].hashpassword;
attr.oldpassword = result[key][i].oldpassword;
attr.salt = result[key][i].salt;
attr.usertype = result[key][i].usertype;
attr.userstatus = result[key][i].userstatus;
}
And you don't need all those .hasOwnProperty checks unless you're modifying native prototypes, which you probably shouldn't. And especially for the Array, it's not necessary if you'd just loop properly with a for instead of a for-in.
exports.listUsers = (req, res) => {
UsersModel.find({}, (err, result) => {
if (err) {
res.send({
code: 400,
failed: 'Error 400'
});
}
let listData = [];
let data = {};
let attr = {};
data.type = result[key].type;
data.id = result[key]._id;
for (let i = 0; i < result[key].length; i++) {
attr.username = result[key][i].username;
attr.email = result[key][i].email;
attr.password = result[key][i].password;
attr.hashpassword = result[key][i].hashpassword;
attr.oldpassword = result[key][i].oldpassword;
attr.salt = result[key][i].salt;
attr.usertype = result[key][i].usertype;
attr.userstatus = result[key][i].userstatus;
}
data.attribute = attr;
listData.push(data);
}
}
let collections = {
"meta": {
"copyright": "Copyright 2018 Kotakku Studio and Lab",
"authors": [
"sw. saputra"
]
},
"link": {
"self": req.protocol + '://' + req.get('host') + req.originalUrl
},
"data": listData
}
res.json(collections);
});
};
I would do something like this with iterating over the keys (this will work dynamically that is even if we don't know key names)
var test=[
{
"type": "users",
"userstatus": "not aktif",
"_id": "5b647bb8998248235a0aab3c",
"username": "luke",
"email": "luke#mail.com",
"password": "password",
"usertype": "bisnis",
"hashpassword": "$2a$10$eyt6YV6m2JJrebNxvS0iEuxMCubDXratNJ6/XK797IGvepXBdp9Yq",
"salt": "2q6eN9U0vWFBsIF1MtB5WrgPiB8pldTS",
"__v": 0
},
{
"type": "users",
"userstatus": "tidak aktif",
"_id": "5b647bdf998248235a0aab3d",
"username": "ken",
"email": "ken#mail.com",
"password": "password",
"usertype": "personal",
"hashpassword": "$2a$10$hok988mszyIBiXVNjmfifOiPNzXkBRRRynXJS/0qCkvlaBOQs65MO",
"salt": "IiMvtVYVqTpZFXmYQIM4IlS6PJFVZ3kw",
"__v": 0
}
]
var listData=[]
test.forEach((obj)=>{
var tempObj={attributes:{}}; //initialize tempObj
Object.keys(obj).forEach((key)=>{
if(key=="_id" || key=="type"){
tempObj[key]=obj[key];
}else{
tempObj.attributes[key]=obj[key];
}
})
listData.push(tempObj);
})
let collections = {
"meta": {
"copyright": "Copyright 2018 Kotakku Studio and Lab",
"authors": [
"sw. saputra"
]
},
"link": {
"self": 'test url'
},
"data": listData
}
console.log(collections)

Accessing second array in a JSON decode using Jquery

I need to access the second array from a JSON decoded string, but I am having no luck.
The entire JSON string is displayed in var RAW00, and then split into var RAW01 & var RAW02.
All 3 of these are for testing - RAW00 is identical to msg
When they are split - I can access either, depending on what variable I start of with, but when I use RAW00 I cannot access the tutor section.
I will provide more detail if required, but my question is:
How do I see and access the tutor array in the second $.each (nested) block??]
Thanks :-)
success: function(msg)
{
var test = "";
var raw00 = {
"allData": [
{
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
]
},
{
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
]
};
var raw01 = {
"allData": [
{
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
]
}
]
};
var raw02 = {
"allData": [
{
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
]
};
$.each(raw00.allData, function(index, entry)
{
$.each(entry.class2, function (index, data)
{
console.log(this.name);
test += '<tr><td>'+this.name+'</td>';
});
$.each(entry.tutor, function (index, data)
{
console.log(this.fname);
test += '<td>'+this.name+'</td></tr>';
});
$('#all-courses-table-content').html( test );
});
You need to check whether the current element of the array is an object with class2 property or tutor property.
$.each(raw00.allData, function(index, entry) {
if (entry.hasOwnProperty('class2')) {
$.each(entry.class2, function (index, data)
{
console.log(this.name);
test += '<tr><td>'+this.name+'</td>';
});
}
if (entry.hasOwnProperty('tutor')) {
$.each(entry.tutor, function (index, data)
{
console.log(this.fname);
test += '<td>'+this.fname+'</td></tr>';
});
}
$('#all-courses-table-content').html( test );
});
Things would probably be simpler if you redesigned the data structure. It generally doesn't make sense to have an array of objects when each object just has a single key and it's different for each. I suggest you replace the allData array with a single object, like this:
var raw00 = {
"allData": {
"class2": [
{
"tid": "1",
"name": "Monday 2"
},
{
"tid": "1",
"name": "Monday Test"
}
],
"tutor": [
{
"fname": "Jeffrey",
"lname": "Kranenburg"
},
{
"fname": "Jeffrey",
"lname": "Kranenburg"
}
]
}
};

Categories

Resources