mongoose: insert data into sub arrays - javascript

I'm I'm trying to create sub arrays with a mongoose and I have a dificulty to insert the subdocuments.
My schema is like this:
var SurveySchema = mongoose.Schema({
question_id: { type: String, unique: true },
question_text: { type: String, required: true },
//answer's object. will contain 4 answers
answers: { type:
[{
answer_id: { type: String, unique: true },
answer_text: { type: String, required: true },
next_question: { type: String, required: true },
platforms: {
type: [{
platform_id: { type: String, required: true },
platform_name: { type: String, required: true },
platform_weight: { type: Number, required: true },
}]
}
}]
}
});
var SurveySchemaExport = module.exports = mongoose.model('Survey', SurveySchema);
And the data that I want to insert into the db looks like this:
{
"question_id": "1",
"question_text": "Freddy",
"answers": [{
"answer_id": "1",
"answer_text": "test1",
"next_question": "ans02",
"platforms": [{
"platform_id": "1",
"platform_name": "Facebook",
"platform_weight": "0.5"
}]
},
{
"answer_id": "2",
"answer_text": "test2",
"platforms": [{
"platform_id": "1",
"platform_name": "Facebook",
"platform_weight": "0.2"
}]
}, {
"answer_id": "3",
"answer_text": "test3",
"platforms": [{
"platform_id": "1",
"platform_name": "Facebook",
"platform_weight": "0.3"
}]
}, {
"answer_id": "4",
"answer_text": "test4",
"platforms": [{
"platform_id": "1",
"platform_name": "Facebook",
"platform_weight": "0.7"
}]
}]
}
My insertion function is like this:
var input = req.body;
var newAlgoData = new SurveySchema({
question_id: input.question_id,
question_text: input.question_text,
answers: [input.answers],
next_question: input.next_question,
platforms: [input.answers.platforms]
})
console.log(newAlgoData);
var isCreated = newAlgoData.save((function (err) {
if (err){
return false;
} else{
return isCreated;
}
}))
The responce I get is:
{ _id: 5b79c144f0a8071048aa8f39,
question_id: '1',
question_text: 'Freddy',
answers: [ { _id: 5b79c144f0a8071048aa8f3a, platforms: [] } ] }
(node:4168) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: newAlgoData.save(...) is not a function
I know how to fix the "not a function" error' ,but my problem is with the insertion of the data into the db, specifically the data in the arrays.
Thank you very much for your help.

Related

How to loop through an array of objects and add a new field using react and javascript?

i want to loop through array of objects and check for a particular property and add a new property "disabled" to the array.
below is the array of objects
const arr_obj = [
{
id: "1",
name: "name1",
type: "type2",
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
so from above array of objects i want to check for each object if type === type2 and if type2 then add property disabled: false if not disabled: true.
below is what i have tried
const new_obj = React.useMemo(() => {
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
}));
}, [arr_obj]);
this adds disabled property only to outer object it doesnt add to children object.
output with above snippet is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
expected output is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
disabled: true,
children: [
{
id: "3",
name: "name3",
type: "type5",
disabled: true,
},
},
{
id: "4",
name: "name4",
type: "type3",
disabled: true,
children: [
{
id: "5",
name: "name5",
type: "type4",
disabled: true,
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
disabled: true
children: [
{
id: "7",
name: "name7",
type: "type4",
disabled: true,
children: [],
},
],
}
},
.....//similar objects
];
How can i fix the above snippet such that it adds disabled property to children too. could someone help me with this. thanks.
EDIT:
tried answer is like below,
function loop_children(children) {
if (!children || children.lengh <=0) {
return;
} else {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
};
}
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(arr.children) //seems like a problem here in adding children field again
}));
but this adds children array under children again.
This code doesnt work. it adds field disabled to children but also adds children within children.
could someone help me with this. thanks.
Not sure why all the others are mapping, just alter the object with a simple recursive call when it has a children property.
const arr_obj = [{
id: "1",
name: "name1",
type: "type2",
children: [{
id: "2",
name: "name2",
type: "type4",
children: [{
id: "3",
name: "name3",
type: "type5",
}, ]
}, ]
}];
const disableEnableObj = (arr, type) => {
arr.forEach(obj => {
obj.disabled = obj.type !== type;
obj.children && disableEnableObj(obj.children, type);
});
}
disableEnableObj(arr_obj, 'type2');
console.log(arr_obj);
You have to loop through the children too. It should look something like this:
function loop_children(children) {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(children)
}));

Populate with condition return null in mongoose

I need to get all production results where machine name is 'CircuitPrinter'
ProductionResult schema:
import { Schema, model } from 'mongoose';
const schemaOptions = {
timestamps: { createdAt: 'created_at', updatedAt: false },
};
const productionResultSchema = new Schema({
machineId: { type: Schema.Types.ObjectId, ref: 'Machine' },
operatorId: { type: Schema.Types.ObjectId, ref: 'Operator' },
orderId: { type: Schema.Types.ObjectId, ref: 'Order' },
elementId: { type: Schema.Types.ObjectId, ref: 'Element' },
}, schemaOptions);
export default model('ProductionResult', productionResultSchema);
Machine Schema
import { Schema, model } from 'mongoose';
const schemaOptions = {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
};
const machineSchema = new Schema({
name: { type: String },
status: { type: String },
date: { type: Date },
amount: { type: Number },
}, schemaOptions);
export default model('Machine', machineSchema);
Service function:
async getBar() {
return ProductionResult.find()
.populate({
path: 'machineId',
match: { name: 'CircuitPrinter' },
});
}
But in response I get machineId with null
Without match I get correct response with full machine data. What's wrong with my condition. Machine with CircuitPrinter name exist in database.
{
"_id": "608c532e4051960ef05176f4",
"machineId": null,
"elementId": "608c4e914051960ef05176cc",
"operatorId": "608c4e914051960ef05176d2",
"orderId": "608c4e914051960ef05176eb",
"created_at": "2021-04-30T18:57:50.771Z",
"__v": 0
}
Edited:
Sample data Machines document:
{
"_id": {
"$oid": "608c4e914051960ef05176ed"
},
"name": "CircuitPrinter",
"status": "Running",
"__v": 0,
"created_at": {
"$date": "2021-04-30T18:38:09.326Z"
},
"updated_at": {
"$date": "2021-04-30T18:38:09.326Z"
}
}
Sample data ProductionResult document:
{
"_id": {
"$oid": "608c532e4051960ef05176f4"
},
"machineId": {
"$oid": "608c4e914051960ef05176f0"
},
"elementId": {
"$oid": "608c4e914051960ef05176cc"
},
"operatorId": {
"$oid": "608c4e914051960ef05176d2"
},
"orderId": {
"$oid": "608c4e914051960ef05176eb"
},
"created_at": {
"$date": "2021-04-30T18:57:50.771Z"
},
"__v": 0
}

Structuring an array the correct way with lodash groupBy

I have an object that looks like this:
{
data: [
{ id: "1", state: "accepted", estimate_date: "2019-12-17" },
{ id: "2", state: "rejected", estimate_date: "2019-12-17" },
{ id: "3", state: "open", estimate_date: "2019-12-17" },
{ id: "4", state: "open", estimate_date: "2019-12-18" },
{ id: "5", state: "rejected", estimate_date: "2019-12-18" },
{ id: "6", state: "accepted", estimate_date: "2019-12-18" },
]
}
When I use lodash groupBy on the object like this:
const key = 'data';
const groupedEstimates = groupBy(estimateData[key], 'estimate_date');
It returns:
[
[
"2019-12-17"
],
[
[ { id: "1", state: "accepted" } ],
[ { id: "2", state: "rejected" } ],
[ { id: "3", state: "open" } ]
]
],
[
[
"2019-12-18"
],
[
[ { id: "4", state: "open" } ],
[ { id: "5", state: "rejected" } ],
[ { id: "6", state: "accepted" } ]
]
]
But now I'm trying to achieve something like this:
[
{
date: "2019-12-17",
items: [
{ id: "1", state: "accepted" },
{ id: "2", state: "rejected" },
{ id: "3", state: "open" },
]
},
{
date: "2019-12-18",
items: [
{ id: "4", state: "open" },
{ id: "5", state: "rejected" },
{ id: "6", state: "accepted" },
]
}
]
Except I don't know how to achieve that using lodash. It doesn't have to use lodash but I only used that at the start as it seemed an easy solution to my problem. Now that I'm trying to achieve a more sensible data structure I would like some insights on how to achieve it.
After grouping by the estimate_date property, iterate the groups object with _.map(). Generate the group's object by taking the key (2nd param) for the date property, and mapping the items to omit the estimate_date:
const estimateData = {"data":[{"id":"1","state":"accepted","estimate_date":"2019-12-17"},{"id":"2","state":"rejected","estimate_date":"2019-12-17"},{"id":"3","state":"open","estimate_date":"2019-12-17"},{"id":"4","state":"open","estimate_date":"2019-12-18"},{"id":"5","state":"rejected","estimate_date":"2019-12-18"},{"id":"6","state":"accepted","estimate_date":"2019-12-18"}]}
const groupedEstimates = _.map(
_.groupBy(estimateData.data, 'estimate_date'),
(items, date) => ({
date,
items: items.map(o => _.omit(o, 'estimate_date'))
})
)
console.log(groupedEstimates)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Aggregate data from nested array

I need help with the aggregate framework.
I have a model (currencies field can contain more than one object):
const schema = new mongoose.Schema({
country: { type: String },
code: { type: String },
region: [{
name: { type: String },
path: { type: Array },
city: [{
name: { type: String },
path: { type: Array },
latitude: { type: String },
longitude: { type: String },
}],
}],
currencies: [{
code: { type: String },
name: { type: String },
symbol: { type: String },
}],
})
And I need to receive all currencies without duplicates.
Received data can view like this:
[
{ code: 'string', name: 'sting', symbol: 'string' },
{ code: 'string', name: 'sting', symbol: 'string' },
...
]
// or like this:
[
currencies: [
{ code: 'string', name: 'sting', symbol: 'string' },
{ code: 'string', name: 'sting', symbol: 'string' },
...
]
]
I try to create a query
Geo.aggregate([
{
$group: {
_id: null,
currencies: { $addToSet: '$currencies' },
},
},
])
but receive this data with duplicates and it has many nested arrays:
[
{
"_id": null,
"currencies": [
[
{
"_id": "5cd9486248989616a411fac5",
"code": "JPY",
"name": "Japanese yen",
"symbol": "¥"
}
],
[
{
"_id": "5cd9491a48989616a411fb47",
"code": "TRY",
"name": "Turkish lira",
"symbol": null
}
],
I try this query:
Geo.aggregate([
{
$addFields: {
code: '$currencies.code',
name: '$currencies.name',
symbol: '$currencies.symbol',
},
},
])
But I receive error "TypeError: item is not iterable".
I need little help )
Db data views like this:
{
"_id": {
"$oid": "5c3334a8871695568817eadf"
},
"country": "Singapore",
"code": "sg",
"region": [
{
"path": [
"Singapore"
],
"_id": {
"$oid": "5c3366c63d92ac6e531e05c0"
},
"city": [],
"name": "Central Singapore Community Development Council"
},
....
],
"__v": 0,
"currencies": [
{
"_id": {
"$oid": "5cd948ec48989616a411fb28"
},
"code": "BND",
"name": "Brunei dollar",
"symbol": "$"
},
{
"_id": {
"$oid": "5cd948ec48989616a411fb27"
},
"code": "SGD",
"name": "Singapore dollar",
"symbol": "$"
}
]
}
In aggregate pipeline first you need to unwind the currencies array and then group them by condition to get desired result.
Geo.aggregate([
{
$unwind: '$currencies'
},
{
$group: {
_id: null,
currencies: { $addToSet: '$currencies' },
},
},
])
For more information you can look into documentation here
db.temp.aggregate([
{$project : {currencies : 1}},
{$unwind: "$currencies"},
{
$addFields: {
currencyHash: {
$concat : ['$currencies.code', "--", "$currencies.name", "--", "$currencies.symbol"]
}
}
},
{
$group: {
_id: "$currencyHash",
currency : {
$first : "$currencies"
}
}
},
{
$project: {
code : "$currency.code",
name : "$currency.name",
symbol : "$currency.symbol"
}
},
{
$project: {
_id : 0,
currency : 0
}
}
]).pretty()

unable to populate articles in mongoose [duplicate]

This question already has answers here:
How to convert string to objectId in LocalField for $lookup Mongodb [duplicate]
(1 answer)
Querying after populate in Mongoose
(6 answers)
Closed 4 years ago.
I have the category schema like this:
var category_article_Schema = new Schema({
"article_id": { type: String, required: false, unique: false },
"category": String,
"articles": [{ type: mongoose.Schema.Types.ObjectId, ref:'article'}],
});
var category_article_Schema = mongoose.model('category_article_Schema', category_article_Schema);
module.exports = category_article_Schema;
Article schema:
var articleSchema = new Schema({
"title": { type: String, required: true, unique: false },
"details": String,
"username": { type: String, required: true, unique: false },
"postImageUrl": String,
"url": String,
"categories": [String],
"created_at": { type: Date, default: Date.now }
});
var article = mongoose.model('article', articleSchema);
module.exports = article;
When I try to populate articles in the below function, I get only category id and name but no articles populated.
function getPostByCategory(req, res, next) {
category_article_model.find({category: req.params.name}) //sports
.populate('articles')
.exec()
.then(function(articlesByCategory) {
console.log(articlesByCategory);
})
.catch(function(err){
console.log('err ', err);
})
}
All the data I have in article collection is this:
`{
"_id": {
"$oid": "5b0008ce8787890004989df1"
},
"categories": [
"sports",
"health"
],
"title": "sample",
"details": "sample ",
"created_at": {
"$date": "2018-05-19T11:21:50.837Z"
},
"__v": 0
},
{
"_id": {
"$oid": "5b0087646dda9600049a9a27"
},
"categories": [
"sports"
],
"title": "sample3333",
"details": " sample3333",
"created_at": {
"$date": "2018-05-19T20:21:56.126Z"
},
"__v": 0
}`
And category_article_schema collection has:
{
"_id": {
"$oid": "5b0087646dda9600049a9a28"
},
"category": "sports",
"article_id": "5b0087646dda9600049a9a27",
"__v": 0
}
But the data returned is empty array of article:
[ { articles: [],
_id: 5b0008ce8787890004989df2,
category: 'sports',
article_id: '5b0008ce8787890004989df1',
__v: 0 } ]
I am not sure what could be the issue?

Categories

Resources