How to normalize paginated data? - reactjs

I need to convert a data like this:
{peopleList: [{id:1, name: 'joe'}, {id: 2, name: 'john'}], page: 1, rowPerPage: 8}
to this model:
{entities: {'0': {id: 0, name: 'joe'}, '1': {id: 1, name: 'john'}, page: 1, rowPerPage: 8}, result: [0, 1]}
but when I add this schema:
const people = new schema.Entity('peopleList');
const normalizedData = normalize(_data, { peopleList: [people] });
I get this output:
{
"entities": {
"peopleList": {
"1": {
"id": 1,
"name": "joe"
},
"2": {
"id": 2,
"name": "john"
}
}
},
"result": {
"peopleList": [
1,
2
],
"page": 1,
"rowPerPage": 8
}
}
I don't know exactly how to make a proper schema that create result filed as my desire. maybe the correct way is to have it in result and this output is correct. any idea?

Related

Count the amount of array-childs / items in received nested array in angular, rxjs

I would like to count the amount of array items from a nested array.
I have done this successfully in a not so deeply nested array, and I am curious how I can create a similar outcome with a one level deeper example.
This is how the well-working one goes:
const listId = this.route.snapshot.paramMap.get('listId');
this.listService.getShortlist(listId)
.subscribe(list =>
{this.list = list;
this.showEditlink = this.list.sublistCreators.find(element => element === this.username);
this.itemcount = this.list.shortlistItem.length;
});
}
The itemcount is what I am looking for. This is usable in my template.
Now, another similar component has the length/count one level deeper, this was my attempt at gaining the array-item-count:
getList(): void {
const listId = this.route.snapshot.paramMap.get('listId');
console.log("het list-id = " + listId);
this.listService.getListNo404(listId)
.subscribe((list =>
{this.list = list;
this.itemcount = this.list.sublist.item.length;
})
)
}
Also tried this (among a lot more):
getList(): void {
const listId = this.route.snapshot.paramMap.get('listId');
console.log("het list-id = " + listId);
this.listService.getListNo404(listId)
.subscribe((list =>
{this.list = list;
this.sublist = this.list.sublist
this.itemcount = this.sublist.item.length;
})
)
}
Here I added the this.sublist = this.list.sublist in between. However not able to get this one working.
Can you help me to count the amount of array-items inside 'item'?
Maybe useful to add, below the json I receive from my backend:
In this particular example the outcomes should be 4 and 3.
{
"_id": {
"$oid": "dummy"
},
"listTitle": "dummy",
"listCreator": "dummy",
"sublist": [
{
"subListCreator": "dummy",
"subListAdded": {
"$date": dummy
},
"item": [
{
"positionId": 1,
"itemScore": 3,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 2,
"itemScore": 2,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 3,
"itemScore": 1,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 4,
"itemScore": 1,
"itemTitle": "dummy",
"itemContext": "dummy"
}
]
},
{
"subListCreator": "dummy",
"subListAdded": {
"$date": dummy
},
"item": [
{
"positionId": 1,
"itemScore": 3,
"itemTitle": "dummy"
},
{
"positionId": 2,
"itemScore": 2,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 3,
"itemScore": 1,
"itemTitle": "dummy"
}
]
}
]
}
Thanks a lot for having a look!
If I understand the problem right, this is something about json and arrays, not about rxjs.
Anyways, again if the understanding is right, the following could be an option.
Let's assume that the myJson constant holds the the json you are providing as example, i.e.
const myJson = {
"_id": {
"$oid": "dummy"
},
.....
}
then a solution could look like this
const subList = myJson.sublist;
const itemList = subList.map((listEl) => listEl.item);
const result = itemList.map((items) => items.length);
What you end up in having in result is an array [4, 3] which is the expected result.
Here a stackblitz example.
I made a small loop to check if we have an Array on key item and if so, we count its length and add it to the sum. If you want any deeper we could introduce recursion on this but I hope this gets you going.
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
itemCount: number;
constructor() {
this.countItems();
}
countItems() {
let count: number = 0;
for (let obj of this.returnObjWithArray(this.target)) {
if (Object.keys(obj).some((key) => key == 'item')) {
console.log('match: ', obj);
console.log('the count:', obj.item.length);
count += obj.item.length;
}
}
console.warn('the sum: ', count);
}
returnObjWithArray(obj: any) {
for (let prop in obj) {
if (Array.isArray(this.target[prop])) {
console.log('the obj with array: ', this.target[prop]);
return this.target[prop];
}
}
}
target = {
_id: {
$oid: 'dummy',
},
listTitle: 'dummy',
listCreator: 'dummy',
sublist: [
{
subListCreator: 'dummy',
subListAdded: {
$date: 'dummy',
},
item: [
{
positionId: 1,
itemScore: 3,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 2,
itemScore: 2,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 3,
itemScore: 1,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 4,
itemScore: 1,
itemTitle: 'dummy',
itemContext: 'dummy',
},
],
},
{
subListCreator: 'dummy',
subListAdded: {
$date: 'dummy',
},
item: [
{
positionId: 1,
itemScore: 3,
itemTitle: 'dummy',
},
{
positionId: 2,
itemScore: 2,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 3,
itemScore: 1,
itemTitle: 'dummy',
},
],
},
],
};
}
console.log()
match:
{subListCreator: "dummy", subListAdded: {…}, item: Array[4]}
the count:
4
match:
{subListCreator: "dummy", subListAdded: {…}, item: Array[3]}
the count:
3
the sum:
7
Here is a working example: https://stackblitz.com/edit/angular-ivy-wpyfox?file=src%2Fapp%2Fapp.component.ts

How to Update Array dict Elements in mongodb based on another field

How can I update a value in a document based on applying functions to another field (which is in a different embedded document)?
With the sample data below, I want to
get the col field for the farm having id 12
multiply that by 0.025
add the current value of the statistic.crypt field
ensure the value is a double by converting it with $toDouble
store the result back into statistic.crypt
data:
{
"_id": {
"$oid": "6128c238c144326c57444227"
},
"statistic": {
"balance": 112570,
"diamond": 14,
"exp": 862.5,
"lvl": 76,
"mn_exp": 2.5,
"lvl_mn_exp": 15,
"coll_ms": 8047,
"all_exp": 67057.8,
"rating": 0,
"crypt": 0
},
"inventory": {
"farm": [{
"id": 12,
"col": 100,
"currency": "diamond",
"cost": 2,
"date": "2021-09-02 18:58:39"
}, {
"id": 14,
"col": 1,
"currency": "diamond",
"cost": 2,
"date": "2021-09-02 16:57:08"
}],
"items": []
},
...
}
My initial attempt is:
self.collection
.update_many({"inventory.farm.id": 12}, [{
"$set": {
"test": {
'$toDouble': {
"$sum": [
{'$multiply':["$inventory.farm.$[].col", 0.025]},
'$test'
]
}
} }
},])
This does not work as it applies to test rather than statistic.crypt, and I cannot figure out how to modify it to apply to statistic.crypt.
A field can be updated based on another in the following stages:
add a field containing the farm
set statistic.crypt to the result of the mathematical expression (applied to the newly embedded farm)
remove extra fields
In code:
self.collection.update_many({"inventory.farm.id": 12 }, [
{
$addFields: {
hh: {
$filter: {
input: "$inventory.farm",
as: "z",
cond: { $eq: ["$$z.id", 12] },
},
},
},
},
{
$set: {
"statistic.crypt": {
$toDouble: {
$sum: [
{
$multiply: [{ $first: "$hh.col" }, 0.025],
},
"statistic.crypt",
],
},
},
},
},
{
$project: {
id_pr: 1,
id_server: 1,
role: 1,
warns: 1,
id_clan: 1,
statistic: 1,
design: 1,
date: 1,
inventory: 1,
voice: 1,
},
},)

Mongodb update nested array by key-value

How can I update nested array by list key value?
{
"_id": "mainId",
"events": [{
"id": 1,
"profile": 10,
} {
"id": 2,
"profile": 10,
} {
"id": 3,
"profile": 20,
}
]
}
and I have a list to update:
var list = {id: 2, newval: 222}, {id: 3, newval: 333}
How can I do an update in one query? Or in MongoDB, it will be like a loop?
for({id, val} in list){
update({_id: "mainId", events.$.id: id}, {setField: {events.$.profile: val}})
}
If you have a copy of the events array, you could make the necessary updates in your code and then send the updated array to MongoDB in a single query. Something like this
db.Test.updateOne({_id: "mainId"}, {$set: { "events": [{id: 1, profile: 222}, {id: 2, profile: 10}, {id: 3, profile: 333}] } } )
If you don't have a copy of the events array, you could do a bulk operation. Something like
db.Test.bulkWrite(
[
{ updateOne : {
"filter": {_id: "mainId", "events.id": 1},
"update": { $set: { "events.$.profile": 222 } }
}
},
{ updateOne : {
"filter": {_id: "mainId", "events.id": 3},
"update": { $set: { "events.$.profile": 333 }}
}
}
]
)
For more on bulkWrite, see the MongoDB docs: https://docs.mongodb.com/manual/core/bulk-write-operations/#bulkwrite-methods

How to loop array after process groupBy in React-Native

i want to grouping data JSON (One JSON) base on region. and the json after grouping like in (Two JSON). and i use the two JSON for show data (Result JSON). so, how to add loop base on region after grouping, because actually i want to show data in front end like (Result JSON):
==>One JSON
data:[
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
]
==> Two JSON
aaa: [
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
],
bbb: [
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
]
==> Result JSON
aaa:
1
3
bbb:
2
thanks
Using Lodash:
const jsonTwo = _.groupBy(data, instance => instance.dataDetail.region);
const resultJson = _.mapValues(jsonTwo, regionInstances => regionInstances.map(instance => instance.id));
Using plain javascript reduce functions:
const jsonTwo = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance)
return accumulator;
},{});
const resultJson = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance.id)
return accumulator;
},{});
var data =
[
{
"id": 1,
"status": "active",
"dataDetail": {
"id": 5,
"name": "tes 1",
"region": "aaa"
}
},
{
"id": 2,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 2",
"region": "bbb"
}
},
{
"id": 3,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 3",
"region": "aaa"
}
}
];
groups =_.chain(data).groupBy('dataDetail.region');
keys = groups.map( (value, key) => key);
values = groups.map( (value, key) => _.map(value, 'id'));
result = _.zipObject(keys, values);

Finding the highest value of object's field with specified _id in array of objects in mongodb

I am new to mongodb. I am doing simple application that uses this database. Here is my doctors collection structure:
{
_id: 1,
name: "David",
specialisation: "dentist",
description: "Super dentist",
treatments: [
{
_id: 0,
price: 2200
},
{
_id: 2,
price: 200
},
{
_id: 5,
price: 2500
},
{
_id: 8,
price: 3200
},
{
_id: 13,
price: 2050
}
],
hospitals: [1, 2, 8, 5, 20]
},
{
_id: 2,
name: "John",
specialisation: "dentist",
description: "Super dentist",
treatments: [
{
_id: 2,
price: 2500
}
],
hospitals: [1]
}
What I want to do, is to get the max value of a treatment with specified id of all doctors in collection. For example in this case if I want to check treatment with _id = 2 it should return 2500, as it is written in John's object.
Any help would be appreciated. Thanks.
Named ur collection as stack
try this
db.stack.aggregate([ {$project:{"treatments._id":1, "treatments.price":1}},
{$unwind:"$treatments"},{$match:{"treatments._id":2}},
{$sort:{"treatments.price":-1}}, {$limit:1} ]);
result: { "_id" : 2, "treatments" : { "_id" : 2, "price" : 2500 } }
ref: https://docs.mongodb.org/manual/reference/operator/aggregation/unwind/

Resources