How to show a nested object as a super object in MongoDB? - javascript

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?

Related

How To Group For Multiple Fields In Sequelize

I need one help related to the sequelize and I am using postgres.
I want to group records in sequelize. Also the form and user value comes after populate or using include method of sequelize.
I have applied this code but it didn't work:-
{
group: ['formId', 'userId', 'responseFrom'],
include: [ { model: forms, as: 'form' }, { model: users, as: 'user' } ]
}
Here the name of table is formAnswers.
[{
"id": 21,
"formId": 1,
"userId": 123,
"formQuestionId": 2,
"answer": "8,5,6",
"responseFrom": "WAITING",
"createdAt": "2020-01-14T02:31:19.173Z",
"form": {
"id": 1,
"name": "Choose Group",
},
"user": {
"id": 123,
"fullName": "Test User",
"username": "test123",
}
},
{
"id": 22,
"formId": 1,
"userId": 123,
"formQuestionId": 1,
"answer": "3",
"responseFrom": "WAITING",
"createdAt": "2020-01-14T02:31:19.178Z",
"form": {
"id": 1,
"name": "Choose Group",
},
"user": {
"id": 123,
"fullName": "Test User",
"username": "test123",
}
}]
This is the sample record, there will be multiple records for each user.
I want to group the records by using formId and userId. Also you can consider responseFrom in group by. I have tried with group in sequelize but its not working.
I need only single record which have formId and userId same. If we are using the above data so the expected output will be:-
[{
"id": 22,
"formId": 1,
"userId": 123,
"formQuestionId": 1,
"responseFrom": "WAITING",
"createdAt": "2020-01-14T02:31:19.178Z",
"form": {
"id": 1,
"name": "Choose Group",
},
"user": {
"id": 123,
"fullName": "Test User",
"username": "test123",
}
}]
I need to apply pagination for this as well so please keep it in mind.
Possible solution: (not tested)
formAnswers.findAll({
attributes: [
sequelize.literal(`DISTINCT ON("form_question_responses"."formId","form_question_responses"."userId","form_question_responses"."responseFrom") 1`),
'id',
'formId',
'userId',
'responseFrom',
],
include: [
{ model: forms, as: 'form', attributes: ['id', 'name'] },
{ model: users, as: 'user', attributes: ['id', 'fullName', 'username'] }
],
// automatically order by as used DISTINCT ON - DISTINCT ON strictly orders based on columns provided
// order: [
// ['formId', 'ASC'],
// ['userId', 'ASC'],
// ],
offset: undefined, // for no offset
limit: 50,
})

Finding all entries of an associated table in Sequelize Js

I am trying to find an array of entries from an associated table while querying from a main table.
Currently I am getting only one entry under the associated table when i try to query.
For example, I am getting an output as follows.
{
"id": 37,
"name": "Mr Tom",
"books": {
"id": 1278,
"name": "Book 1",
}
}
As you can see the books part comes as an object in an array. I am expecting it to be an array of books.
The following is the code I am using to query the data.
const authorId = req.params.id;
const AuthorDetails = await AUTHOR.findOne({
attributes: [
'id',
'name',
],
where: {
id: authorId,
},
include: [
{
model: BOOKS,
attributes: ['id','name'],
},
],
raw: true,
nest: true,
});
The relationship between the author and books is one to many. Where a
book can have only one author but an author can have many books.
This is defined as follows.
AUTHORS.hasMany(BOOKS);
BOOKS.belongsTo(AUTHORS);
edit: I noticed that when i remove the condition id:authorId it duplicates the author object and gives a unique book . For example
[
{
"id": 37,
"name": "Mr Tom",
"books": {
"id": 1278,
"name": "Book 1",
}
},
{
"id": 37,
"name": "Mr Tom",
"books": {
"id": 1279,
"name": "Book 2",
}
}
]

Loop through nested json array to create new array

I am working on a lambda function that GETs data from one API and POSTs it to another. The data is a list of contacts with properties, e.g. first name, last name, email, etc.
The JSON output contains too many properties that I don't need. See below code example (actual code contains many more properties and nested arrays/objects).
{
"contacts": [
{
"addedAt": 1532803458796,
"vid": 101
}
],
"merge-audits": [],
"properties": {
"first-name": {
"value":"hello"
},
"last-name": {
"value":"there"
},
"email": {
"value":"hello#there.com"
}
...
...
}
How can I loop through each JSON object to create a new, simpler JSON array like the following:
[
{
"email": "example#example.com",
"first_name": "",
"last_name": "User"
},
{
"email": "example2#example.com",
"first_name": "Example",
"last_name": "User"
}
]
Thanks in advance for your help.
try
json.map( x => ({
email: x.properties.email.value,
first_name: x.properties['first-name'].value,
last_name: x.properties['last-name'].value,
}));
let json = [
{
"contacts": [{
"addedAt": 1532803458796,
"vid": 101
}],
"merge-audits": [],
"properties": {
"first-name": {
"value": "hello"
},
"last-name": {
"value": "there",
},
"email": {
"value": "hello#there.com"
}
}
},
{
"contacts": [{
"addedAt": 1532803458796,
"vid": 101
}],
"merge-audits": [],
"properties": {
"first-name": {
"value": "Tom"
},
"last-name": {
"value": "Smith",
},
"email": {
"value": "tom#smith.com"
}
}
}
]
let r = json.map(x => ({
email: x.properties.email.value,
first_name: x.properties['first-name'].value,
last_name: x.properties['last-name'].value,
}));
console.log(r);
You could use a destructuring assignment for the object and short hand properties for the mapping.
var data = [{ contacts: [{ addedAt: 1532803458796, vid: 101 }], "merge-audits": [], properties: { "first-name": { value: "hello" }, "last-name": { value: "there" }, email: { value: "hello#there.com" } } }],
result = data.map(({ properties: {
'first-name': { value: first_name },
'last-name': { value: last_name },
email: { value: email }
} }) => ({ first_name, last_name, email }));
console.log(result);

push elements of each object inside each object inside another array

I have two arrays, one is my original one called data which consists of :
const datas = [
{
name: 'core Test',
item: [
{
name: 'test/core/core.js',
item: "item1"
}
]
},
{
name: 'users Test',
item: [
{
name: 'test/users/user.js',
item: "item2"
}
]
}
]
And i have another array called replace, which i'm trying to push each of its elements inside my original one, inside the
const replace = [
{
type: "test1",
number: "1",
},
{
type: "test2",
number: "2",
}
]
Here is my code :
const transformedData = datas.map(data => {
data.item = data.item.map(x => ({
name: x.name,
type: replace.map(y=>{return y;})
}))
return data
})
The output i get :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
}
]
The output i want :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": { "type": "test1", "number": "1" }
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": { "type": "test2", "number": "2" }
}
]
}
]
This is because you're mapping all the way through the replace array every single time for each time you're inside of a value inside of datas. Instead you want to keep track of the index with your original map so then you only have one instance each time.
Try something like:
const transformedData = datas.map((data, index) => {
data.item = data.item.map(x => ({
name: x.name,
type: replace[index]
}))
return data;
});

How to normalize this with normalizr?

Consider the User object passed back:
{
"id": "123",
"username": "TestUser",
"group":
{
"id": "324",
"name": "My Group"
}
}
I want to run: normalize(user);
And get something like this back. Is it possible? Or is it correct? I am trying to extract the group from the user, so I can place it in its own entities slot.
{
result: "123",
entities: {
"users": {
"123": {
id: "123",
group: "1",
username: "TestUser
}
},
"groups": {
"1": { "id": "324", "name": "My Group" },
}
}
}
I'm not quite sure what my schemas should look like to achieve this result.
Figured it out. Didn't realize it was so straightforward.
export const group = new schema.Entity('groups', {}, {
idAttribute: 'id'
});
export const user = new schema.Entity(
'users',
{
group: group
},
{
idAttribute: 'id'
}
);

Categories

Resources