Normalizr normalize nested data - javascript

I have a nested data which looks like this:
{
components: [
guid: "cms-container/c154c79596b3af6326966b0c994e2a934",
regions: [{
guid :"r1c154c79596b3af6326966b0c994e2a934",
components: [{
guid: "cms-markupfile/owg-header.html" },
{ guid: "cms-navmenu/n1503636374400" },
{ guid: "cms-container/c50c451ba72e4b4edab979cf477129215",
regions: [{
guid: "r1c50c451ba72e4b4edab979cf477129215",
components: [{
guid:"cms-serie/serieDetailRenderer"
}]
}]
},
]
}]
]
}
As you can see this is a nested structure with arbitrary nesting.
That is, in the components array there can be also an array of region in which, in turn, there can be another components array.
I'm trying to bring this structure to a flat form with normalizr but so far without result. I would be grateful for the help in solving this problem.

I would try something as simple as that :
import { schema } from 'normalizr'
const schemas = {
component: new schema.Entity('components'),
region: new schema.Entity('regions')
}
schemas.component.define({
regions: [schemas.region]
})
schemas.region.define({
components: [schemas.component]
})
I'm afraid of circular references, but it's worth trying.
If it's not working can you supply what you've done so far ?

Old question, but the answer might be useful to someone.
If I understand correctly, each component contains unique identifier (guid) and possibly an array of regions, while each region contains unique identifier (guid) and possibly an array of components. If that is the case, you are missing a couple of {} inside the outermost components array. Instead of
{
components: [
you should write
{
components: [{
And at the end, instead of
]
}
you should write
}]
}
Now, suppose my understanding of your data is correct, and suppose you make correction as suggested, your normalizr schema should look as folowing:
import { schema, normalize } from 'normalizr'
const regionSchema = new schema.Entity(
'regions',
{ components: [ componentSchema ] },
{ idAttribute: 'guid' }
)
const componentSchema = new schema.Entity(
'components',
{ regions: [ regionSchema ] },
{ idAttribute: 'guid' }
)
and you should normalize your data like this
let data = [{
guid: "cms-container/c154c79596b3af6326966b0c994e2a934",
regions: [{
guid :"r1c154c79596b3af6326966b0c994e2a934",
components: [{
guid: "cms-markupfile/owg-header.html" },
{ guid: "cms-navmenu/n1503636374400" },
{ guid: "cms-container/c50c451ba72e4b4edab979cf477129215",
regions: [{
guid: "r1c50c451ba72e4b4edab979cf477129215",
components: [{
guid:"cms-serie/serieDetailRenderer"
}]
}]
},
]
}]
}]
let normalizedData = normalize(data, [componentSchema])

Related

Mongodb find documents with given field value inside an array and its id in another array inside the same document

My data model:
{
_id: ObjectId,
persons:[{
_id: ObjectId,
name: String,
...
}],
relations: [{
type: String,
personId: ObjectId,
...
}],
...
}
Here's my issue:
I am trying to find documents where person's name is x and it's _id is inside the relations array (personId) with a given type.
Example:
My data:
[{
_id:"1",
persons:[{
_id:"1",
name: "Homer"
},
{
_id:"2",
name: "Bart"
}],
relations: [{
type:"House_Owner",
personId: 1,
}],
}]
Request_1:
Find all documents where "Homer" is the house owner
Result:
[{
_id:"1",
...
}]
Request_2:
Find all documents where "Bart" is the house owner
Result:
[]
Any help would be appreciated.
The only solution I see here is to do the find operation with the given name value and after that filter the mongodb result.
PS: I cannot change the existing data model
EDIT:
I found a solution to do this by using $where operator with a javascript function but I am not sure that's the most efficient way.
db.myCollection("x").find({
$where: function() {
for (const relation of this.relations) {
if(relation.type === "House_Owner") {
for (const person of this.persons) {
if(person.name === "Homer" && person._id.equals(relation.personId)) {
return true;
}
}
}
}
}
})
You can do something like this:
const requiredName="x"
const requiredId = "id"
await yourModel.find({$and:[{"relations.personId":requiredId },{"persons.name":requiredName}]})

Edit multiple objects in array using mongoose (MongoDB)

So I tried several ways, but I can't, I can modify several objects with the same key but I can't modify any with different keys, if anyone can help me is quite a complex problem
{
id: 123,
"infos": [
{ name: 'Joe', value: 'Disabled', id: 0 },
{ name: 'Adam', value: 'Enabled', id: 0 }
]
};
In my database I have a collection with an array and several objects inside which gives this.
I want to modify these objects, filter by their name and modify the value.
To give you a better example, my site returns me an object with the new data, and I want to modify the database object with the new object, without clearing the array, the name key never changes.
const object = [
{ name: 'Joe', value: 'Hey', id: 1 },
{ name: 'Adam', value: 'None', id: 1 }
];
for(const obj in object) {
Schema.findOneAndUpdate({ id: 123 }, {
$set: {
[`infos.${obj}.value`]: "Test"
}
})
}
This code works but it is not optimized, it makes several requests, I would like to do everything in one request, and also it doesn't update the id, only the value.
If anyone can help me that would be great, I've looked everywhere and can't find anything
My schema structure
new Schema({
id: { "type": String, "required": true, "unique": true },
infos: []
})
I use the $addToSet method to insert objects into the infos array
Try This :
db.collection.update({
id: 123,
},
{
$set: {
"infos.$[x].value": "Value",
"infos.$[x].name": "User"
}
},
{
arrayFilters: [
{
"x.id": {
$in: [
1
]
}
},
],
multi: true
})
The all positional $[] operator acts as a placeholder for all elements in the array field.
In $in you can use dynamic array of id.
Ex :
const ids = [1,2,..n]
db.collection.update(
//Same code as it is...
{
arrayFilters: [
{
"x.id": {
$in: ids
}
},
],
multi: true
})
MongoPlayGround Link : https://mongoplayground.net/p/Tuz831lkPqk
Maybe you look for something like this:
db.collection.update({},
{
$set: {
"infos.$[x].value": "test1",
"infos.$[x].id": 10,
"infos.$[y].value": "test2",
"infos.$[y].id": 20
}
},
{
arrayFilters: [
{
"x.name": "Adam"
},
{
"y.name": "Joe"
}
],
multi: true
})
Explained:
You define arrayFilters for all names in objects you have and update the values & id in all documents ...
playground

How to place these 2 arrays inside separate objects and push to the main array in JS?

I have 2 filtered arrays:
productsByCategory,
productsByTag
so I need to get the following structure:
this.filteredProducts = [{
type: 'Category'
products: productsByCategory // it's array
}, {
type: 'Tag'
products: productsByTag // it's array
}]
So this should be the end result. I am using Vue.js and lodash. How can be this achieved in an elegant way?
A good straight-forward answer can be given if you say the intention behind that structuring otherwise you could just use a method to accomplish that.
{
data() {
return {
productsByCategory: [],
productsByTag: [],
filteredProducts: []
};
},
methods: {
groupProducts() {
this.filteredProducts.push({
type: "Category",
products: this.productsByCategory
});
this.filteredProducts.push({
type: "Tag",
products: this.productsByTag
});
}
}
}

How to create an array as such using javascript

Using javascript, I want to create an array that has the structure so that it can have all states within the country array. Each state would be an array consisting all the regions within it. And each region would contain all the health clubs within it. Something like this:
[Australia]=>array([NSW]=>array([Sydney]=>array(element1, element2, ...)));
So far I have tried many things including the code below:
$('#search-widget-data li').each(function(){
var dataElement = $(this);
searchWidgetData.push(dataElement.text());
alldata.push([dataElement.prevAll(".state:first").text(),
dataElement.prevAll(".region:first").text());
});
You can use a form like this:
var countries = [
{
name: "Australia",
states: [
{
name: "state1",
regions: [
{
name: "region1",
healthclubs: [
"healthclub1", "healthclub2"
]
},
{
name: "region2",
healthclubs: [
"healthclub1", "healthclub2"
]
}
]
},
{
name: "state2",
regions: [
{
name: "region1",
healthclubs: [
"healthclub1", "healthclub2"
]
}
]
}
]
},
{
name: "USA"
}
];
You may want to store your data structure in the JSON format which will make it easy for storage and working with as a JavaScript object.
You may try this one out.
var regArr[n1][n2];
but you need to specify the length of each inner array.

Is there a way to support nested resources in the ember REST adapter?

The default REST Adapter expects a model like this where the dependent objects are loaded alongside the one they have a many-to-one relationship with.
{
object: {
...
}
dependentObjects: [
...
]
}
But is there any adapter that supports data in a nested format like this?
{
object: {
...
dependentObjects: [
...
]
}
}
You can embed records in your response from API, but you need to configure your serializer properly:
App.ParentSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
isNewSerializerAPI: true,
attrs: {
children: { embedded: 'always' }
}
});
Then, you could serialize following response:
{
parents: [
{
id: 1,
children: [
{
id: 1,
name: 'a'
}
]
}
]
}
Working demo.
Read more about embedded records.

Categories

Resources