This question already has answers here:
Does JavaScript guarantee object property order?
(13 answers)
Closed 3 years ago.
I have an express API using an already populated mongoDB and have defined the schema like so:
const accountHolderSchema= new mongoose.Schema({
pid: {Type: Number},
accountNumber: {type: String},
relationshipType: {type: String},
firstName: {type: String},
middleName: {type: String},
lastName: {type: String}
});
const accountsSchema = new mongoose.Schema({
accountNumber: String,
accountType: String,
accountHolder: [accountHolderSchema]
});
const productDetailSchema = new mongoose.Schema({
pid: Number,
accounts: [accountsSchema]
});
I have literally copied and paste all the properties and from the database so i know they match so i know that's out of the picture
The RESPONSE I get is this:
{
"pid": 2697143,
"accounts": [
{
"accountHolders": [
{
"pid": 13209741,
"accountNumber": "403716000062",
"relationshipType": "BENEFICIARY",
"firstName": "Maria",
"middleName": "Delores",
"lastName": "Jackson"
}
]
"accountNumber": "12345",
"accountType": "RSA",
}
]
}
BUT what the response I WANT to get in return is this:
{
"pid": 2697143,
"accounts": [
{
"accountNumber": "12345",
"accountType": "RSA",
"accountHolders": [
{
"pid": 13209741,
"accountNumber": "403716000062",
"relationshipType": "BENEFICIARY",
"firstName": "Maria",
"middleName": "Delores",
"lastName": "Jackson"
}
]
}
]
}
I want the accountNumber and accountNumber to come before accountHolders field.
I'm not sure if its the way how i define a nested array inside of another nested array that's throwing of the structure. If I don't the define accountHolderSchema the structure is returned fine. Any ideas?
If the order of the propreties is really important to you, you could use some simple JavaScript.
Loop through your Schema propreties and assign the propreties to an obj.
(Object.keys(obj)) will return an array with the propreties, then you make an organized copy of your document by getting the keys from the array and assigning values from the document.
let schema = {
"pid": 2697143,
"accounts": [
{
"accountNumber": "12345",
"accountType": "RSA",
"accountHolders": [
{
"pid": 13209741,
"accountNumber": "403716000062",
"relationshipType": "BENEFICIARY",
"firstName": "Maria",
"middleName": "Delores",
"lastName": "Jackson"
}
]
}
]
}
let doc = {
"pid": 2697143,
"accounts": [
{
"accountHolders": [
{
"pid": 13209741,
"accountNumber": "403716000062",
"relationshipType": "BENEFICIARY",
"firstName": "Maria",
"middleName": "Delores",
"lastName": "Jackson"
}
],
"accountNumber": "12345",
"accountType": "RSA",
}
]
}
let docOrganized= {};
docOrganized.pid = doc.pid;
Object.keys(schema.accounts[0]).map(key => docOrganized[key] = doc.accounts[0][key]);
console.log(docOrganized);
Related
This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 3 years ago.
I'm creating a web application. I have some data from the backend and I have to manipulate it to create my front end application the problem demo is shown below.
I have an object something like in javascript
[
{
id: "1",
projectId: "1",
user: {
id: "123",
firstName: "aaaa",
lastName: "bbb",
title: "SE"
}
},
{
id: "2",
projectId: "2",
user: {
id: "456",
firstName: "ccc",
lastName: "fff",
title: "QA"
}
}
]
I need to convert this to:
[
{
id: "123",
firstName: "aaaa",
lastName: "bbb",
title: "SE"
},
{
id: "456",
firstName: "ccc",
lastName: "fff",
title: "QA"
}
]
map over your original data and return only the user object
const data = [
{
id: "1",
projectId: "1",
user: {
id: "123",
firstName: "aaaa",
lastName: "bbb",
title: "SE"
}
},
{
id: "2",
projectId: "2",
user: {
id: "456",
firstName: "ccc",
lastName: "fff",
title: "QA"
}
}
]
const mapped = data.map(obj => obj.user)
console.log(mapped)
since you have an array of objects and you want to access an object inside this element
you can do this
const newData = data.map(({user})=>user)
This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 3 years ago.
I Want to separate the elements from an array of objects in to another array
emplist = [
{
"empid": "CL4NX1569868029",
"orgid": "ZARQP1569826662",
"accid": "95057056798",
"fstname": "Testname",
"lastname": "Last",
"email": "test.mk#gmail.com"
},
{
"empid": "HMXEN1569860677",
"orgid": "ZARQP1569826662",
"accid": "9505705709",
"fstname": "Testname1",
"lastname": "Last",
"email": "test.mk#gmail.com"
},
{
"empid": "UX74A1569908006",
"orgid": "ZARQP1569826662",
"accid": "9100",
"fstname": "abc",
"lastname": "abc",
"email": "abc#abc.com"
},
]
I want to separate fstname and lastname like
source = [ "Testname Last" , "Testname1 Last" , "abc abc" ]
You can simply use map to transform the emplist array into another array with first and last names concatenated (here I used template literal, but you can just use +).
const emplist = [
{
"empid": "CL4NX1569868029",
"orgid": "ZARQP1569826662",
"accid": "95057056798",
"fstname": "Testname",
"lastname": "Last",
"email": "test.mk#gmail.com"
},
{
"empid": "HMXEN1569860677",
"orgid": "ZARQP1569826662",
"accid": "9505705709",
"fstname": "Testname1",
"lastname": "Last",
"email": "test.mk#gmail.com"
},
{
"empid": "UX74A1569908006",
"orgid": "ZARQP1569826662",
"accid": "9100",
"fstname": "abc",
"lastname": "abc",
"email": "abc#abc.com"
},
];
const source = emplist.map((emp) => `${emp.fstname} ${emp.lastname}`);
console.log(source);
I'm using nodejs, couchdb for my application. In the future, if I want to check whether my documents look like the same as a model, I'm thinking to fetch all the documents and compare with the model or a schema and add the missing field to the document as null and update it. How to compare and find out the specific missing field and add it to the document(json object).
Model/Schema
{
"_id": "",
"email": "",
"password": "",
"mobile": "",
"username": "",
"sharedNetworksArr": []
}
After I have fetched my documents and if some of the documents look like below, I have to add the missing fields.
{
"_id": "1",
"email": "abc#gmail.com",
"password": "abc",
"username": "abc"
}
The output should be as,
{
"_id": "1",
"email": "abc#gmail.com",
"password": "abc",
"mobile": "",
"username": "abc",
"sharedNetworksArr": []
}
Note
All the documents may not miss the same field and some documents might be exact as the output.
You could use ES6 spread operator like this
If you are using a single object
// Model/Scheme Object
const modelObject = {
"_id": "",
"email": "",
"password": "",
"mobile": "",
"username": "",
"sharedNetworksArr": []
};
// document returned object
const documentObject = {
"_id": "1",
"email": "abc#gmail.com",
"password": "abc",
"username": "abc"
};
/*
Get the result using ES6 spread operator by passing
the model object first, and the document object second
*/
const outputObject = { ...modelObject, ...documentObject };
console.log(outputObject);
/*
{ _id: '1',
email: 'abc#gmail.com',
password: 'abc',
mobile: '',
username: 'abc',
sharedNetworksArr: []
}
*/
If you are using an array of objects. Use the Array map operator to transform the result
const documentObjectArray = [{
"_id": "1",
"email": "abc#gmail.com",
"password": "abc",
"username": "abc"
}, {
"_id": "2",
"email": "def#gmail.com",
"password": "def",
"username": "def"
}, {
"_id": "3",
"email": "ghi#gmail.com",
"password": "ghi",
"username": "ghi"
}];
const outputObjectArray = documentObjectArray.map((document) => {
/* transform result using ES6 spread operator by passing
the model object first, and the document object second */
return { ...modelObject, ...document, }
});
console.log(outputObjectArray);
/*
[ { _id: '1',
email: 'abc#gmail.com',
password: 'abc',
mobile: '',
username: 'abc',
sharedNetworksArr: [] },
{ _id: '2',
email: 'def#gmail.com',
password: 'def',
mobile: '',
username: 'def',
sharedNetworksArr: [] },
{ _id: '3',
email: 'ghi#gmail.com',
password: 'ghi',
mobile: '',
username: 'ghi',
sharedNetworksArr: [] } ]
*/
You can use lodash's defaultsdeep (or just defaults) library for this.
const _defaultsDeep = require('lodash.defaultsdeep');
let base = {
"_id": "",
"email": "",
"password": "",
"mobile": "",
"username": "",
"sharedNetworksArr": []
};
let input = {
"_id": "1",
"email": "abc#gmail.com",
"password": "abc",
"username": "abc"
};
let merged = _defaultsDeep(input, base);
console.log(JSON.stringify(merged, null, 2));
You can give default value in to the model.Or you should add required field for other.
{ "_id": "", "email": "", "password": "", "mobile": "", "username": "",
"sharedNetworksArr": {default:[]} }
As it is stated here, I had to save reference objects inside of a nested key called 'item';
var userSchema = new Schema({
name: String,
connections: [{
kind: String,
item: { type: ObjectId, refPath: 'connections.kind' }
}]
});
var organizationSchema = new Schema({ name: String, kind: String });
var User = mongoose.model('User', userSchema);
var Organization = mongoose.model('Organization', organizationSchema);
In my DB, it is more like this:
var childSchema = new Schema({
kind: String,
item: {
type: Schema.Types.ObjectId,
refPath: 'children.kind'
}
},{ _id : false, strict:false });
var schema = new Schema({
name: String,
kind: String,
children: [childSchema]
},{
strict: false
});
Now, it is a tree based folder structure model, and it can have either a Folder or a Leaf as child object.
I needed a recursive populate, so I find an answer on SO, it became like this;
var autoPopulateChildren = function(next) {
this.populate({path:'children.item', select:'name id children'});
next();
};
schema.pre('findOne', autoPopulateChildren)
.pre('find', autoPopulateChildren)
Now, when I make a find query, I get this-like example;
{
"name": "Some Folder",
"children": [
{
"kind": "Leaf",
"item": {
"name": "First Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
},
{
"kind": "Folder",
"item": {
"name": "First Level Folder",
"id": "5b61d844d77fb30b9537e5d1"
"children": [
{
"kind": "Leaf",
"item": {
"name": "Second Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
}
]
}
}
],
"id": "5b61c85f25375fddf6048d3d"
}
But now, I need to get rid of 'kind' (don't show) and also I need to show 'item' object as a child (it should be name instead of item:{name:'a'}:
{
"name": "Some Folder",
"children": [
{
"name": "First Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
},
{
"name": "First Level Folder",
"id": "5b61d844d77fb30b9537e5d1"
"children": [
{
"name": "Second Level Leaf",
"id": "5b61c85f25375fddf6048d3c"
}
]
}
],
"id": "5b61c85f25375fddf6048d3d"
}
How can I do this on autoPopulateChildren function?
i am having the Array of objects like this
var result={
"employees": [
{
"_id": "5796e7a27d075bd0453b7751",
"firstName": "Test4",
"schemaName": "Employee"
},
{
"_id": "5796e78e7d075bd0453b774f",
"firstName": "Test 3",
"schemaName": "Employee"
},
{
"_id": "5790b203df5ad69025e8a20b",
"email": "df#gmail.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Jeevan",
"email": "ddd#asd.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Chethan",
"email": "ddd#asd.com",
"schemaName": "Employee"
}
]
};
};
but i want uniq objects by email. i am using lodash uniq but its Not giving proper Result. here i tried this code.
var combined=result.employees.map(function(employee){
employee.schemaName='Employee';
return employee;
});
combined = _.uniq(combined, 'email');
console.log(combined);
The Result is coming like this.
[ { _id: '5796e7a27d075bd0453b7751',
firstName: 'Test4',
schemaName: 'Employee' },
{ _id: '5790b203df5ad69025e8a20b',
email: 'df#gmail.com',
schemaName: 'Employee' },
{ _id: '577f69cc789df5ec1e995513',
firstName: 'Jeevan',
email: 'ddd#asd.com',
schemaName: 'Employee' } ]
i want the objects which are not having email ids and i want only objects which are unique emailid's can anybody help me on this. I want the Result contain the objects Which are not having email id also. The Result should be like this.
[ { _id: '5796e7a27d075bd0453b7751',
firstName: 'Test4',
schemaName: 'Employee' },
{ _id: '5796e78e7d075bd0453b774f',
firstName: 'Test3',
schemaName: 'Employee' },
{ _id: '5790b203df5ad69025e8a20b',
email: 'df#gmail.com',
schemaName: 'Employee' },
{ _id: '577f69cc789df5ec1e995513',
firstName: 'Jeevan',
email: 'ddd#asd.com',
schemaName: 'Employee' } ]
This could make it too.
_.uniqBy(result.employees, function(employee){return employee.email || employee._id;});
I would recommend the use of _.uniqWith for this with your own comparator.
var result = {
"employees": [
{
"_id": "5796e7a27d075bd0453b7751",
"firstName": "Test4",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5796e78e7d075bd0453b774f",
"firstName": "Test 3",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5796e77e7d075bd0453b774d",
"firstName": "Test 2",
"lastName": "T",
"__v": 0,
"documents": [],
"schemaName": "Employee"
},
{
"_id": "5796e7707d075bd0453b774b",
"firstName": "Test1",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5790b203df5ad69025e8a20b",
"firstName": "Ganesh",
"lastName": "dsf",
"__v": 0,
"email": "df#gmail.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Jeevan",
"__v": 0,
"email": "fs#asf.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Chethan",
"__v": 0,
"email": "fs#asf.com",
"schemaName": "Employee"
}
]
};
// Create a lodash chain from the employees.
combined = _.uniqWith(result.employees, function(e1, e2){
return e1.email && e1.email === e2.email;
});
console.log(combined);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>
I'm using a deepEquals algorithm so this code becomes more general. If you want to check only by email, just change the equals function below.
const equals =
// Naïve deepEquals, only for demo. Doesn't work if keys orders vary.
(obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2);
// A real deepEquals:
// https://www.npmjs.com/package/fast-deep-equal
const uniq = (el1, index1, array) =>
array.every((el2, index2) => index1 <= index2 || !equals(el1, el2));
[{ a: 1, b: 2 }, { c: 3 }, { a: 1, b: 2 }, { d: 4 }, { a: 1, b: 2 }].filter(uniq);
// Result: [ { a: 1, b: 2 }, { c: 3 }, { d: 4 } ]