override object properties in createAsyncThunk method - redux-toolkit

I have a function like this
export const fetchChildrenNews = createAsyncThunk('news/fetch1', async ([item, news]) => {
const res = await Promise.all(item.kids.map(id => {
let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`;
return fetch(url);
}));
const jsons = await Promise.all(res.map(r => r.json()));
let users = {...item, kids: jsons};
item.kids = []//doesn't work
item.id = 0 //doesn't work
//I want to find a branch in the original tree and replace it
const tree = (obj) => {
for (let key in obj) {
if (key === "id" && obj[key] === users.id) {
obj = users;
}
if (key == "kids") {
tree(obj);
}
}
}
tree(item);
where item is a nested object record: {by: 'nullzzz', descendants: 47, id: 28808556, kids: Array(13), score: 117}. kids property contains array of ids and in the users variable it becomes an array of records. and my goal change record.kids = [0, 7, 14] to record.kids = users ([{by: '...', id:4848,..], [{by: 'adasd'], [{by: 'zzz}] ). the variable news is a whole tree while item its branches.
I just started working with the toolkit, so I don't fully understand this

Since item is probably an object from your Redux store, that thunk would try to modify a reference to your store - and modifying the store is only allowed in reducers.
Generally, you should be doing logic like this in reducers, not in a thunk.
So, do
export const fetchChildrenNews = createAsyncThunk('news/fetch1', async ([item, news]) => {
const res = await Promise.all(item.kids.map(id => {
let url = `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`;
return fetch(url);
}));
const jsons = await Promise.all(res.map(r => r.json()));
return jsons
})
and then in your slice, add the logic:
builder.addCase(fetchChildrenNews, (state, action) => {
const jsons = action.payload
// here, do not modify `items`, but modify `state` - I would assume `items` is somewhere in here anyways?
})

Related

how to update a collection if you already called it MongoDB Mongoos

Ok so I have a problem in which I use a collection to gather some ratings data and work with it, by the time I finish the rating update process, I have new ratings that I would like to update the collection with. However I can't call update because I get the error "Cannot overwrite model once compiled." I understand that I already called once the model to work with the data and that's why I get the error. is there any way I can update the collection? Or I will just have to workaround by creating a new collection with the latest rating, and then matching the latest ratings collection with the one I use to work with the data.
This is my code
let calculateRating = async () => {
const getData = await matchesCollection().find().lean();
const playerCollection = await playersCollection();
const getDataPlayer = await playerCollection.find().lean();
let gamesCounting = [];
getDataPlayer.forEach((player) => {
player.makePlayer = ranking.makePlayer(1500);
});
for (let i = 0; i < getData.length; i++) {
const resultA = getDataPlayer.findIndex(({ userId }, index) => {
if (userId === getData[i].userA) {
return index;
}
});
const resultB = getDataPlayer.findIndex(
({ userId }) => userId === getData[i].userB
);
const winner = getData[i].winner;
if (getDataPlayer[resultA] === undefined) {
continue;
} else if (getDataPlayer[resultB] === undefined) {
continue;
}
gamesCounting.push([
getDataPlayer[resultA].makePlayer,
getDataPlayer[resultB].makePlayer,
winner,
]);
}
ranking.updateRatings(gamesCounting);
let ratingsUpdate = [];
getDataPlayer.forEach((item) => {
let newRating = item.makePlayer.getRating();
let newDeviation = item.makePlayer.getRd();
let newVolatility = item.makePlayer.getVol();
item.rating = newRating;
item.rd = newDeviation;
item.vol = newVolatility;
ratingsUpdate.push(item);
});
};
I try the work around with creating the new collection

Prisma executeRaw batch operation save incorrectly Float values

does anyone have some bad experience with saving float via executeRaw batch operation? Or at least an idea of how to solve my problem: ExecuteRaw is saving numbers like 7.76e-322. Input is 157 and saved value is 7.76e-322.
const items = [{uniqueId: 1, price: 100},{uniqueId: 2, price: 200}];
const completeKeys: string[] = Object.keys(items[0]);
const updateFieldsMapper = (item: any) => {
return Prisma.sql`(${Prisma.join(
completeKeys.map((key: string) => item[key])
)})`;
};
const insertKeys = completeKeys.map((key) =>
key.toLocaleLowerCase() !== key ? `"${key}"` : `${key}`
);
let insertValues = completeKeys.map((item) => updateFieldsMapper(item));
const updateSet = completeKeys.reduce((updateSet: string[], key: string) => {
if (!ingnoredKeys.includes(key)) {
updateSet.push(`"${key}" = EXCLUDED."${key}"`);
}
return updateSet;
}, []);
try {
await prisma.$executeRaw`
INSERT INTO "Product" (${Prisma.raw(insertKeys.join(","))})
VALUES ${Prisma.join(insertValues)}
ON CONFLICT (uniqueId)
DO UPDATE SET ${Prisma.raw(updateSet.join(","))};`;
} catch (error) {
console.error(util.inspect(error, false, null, true));
Sentry.captureException(error);
}
Thank you very much

How to EF.Property<T> method works with included queries

I trying write a generic method for create response to datatables ajax request;
public static Response<T> CreateResponse<T>(IQueryable<T> query, Request request) where T : class
{
query = query.AsNoTracking();
var filtered = query;
if (!string.IsNullOrEmpty(request.Search.Value))
{
var keywords = Regex.Split(request.Search.Value, #"\s+").ToList();
request
.Columns
.Where(p => p.Searchable)
.ToList()
.ForEach(c =>
keywords.ForEach(k =>
{
filtered = filtered.Intersect(query.Where(p => EF.Functions.Like(EF.Property<string>(p, c.Name), $"%{k}%")));
})
);
}
var ordered = filtered;
request.Order.ForEach(p => ordered = p.Dir == "asc" ? ordered.OrderBy(q => EF.Property<T>(q, request.Columns[p.Column].Name)) : ordered.OrderByDescending(q => EF.Property<T>(q, request.Columns[p.Column].Name)));
var paged = ordered.Skip(request.Start).Take(request.Length);
return new Response<T> { draw = request.Draw, recordsTotal = query.Count(), recordsFiltered = filtered.Count(), data = paged.ToList() };
}
My problem is, when query parameter is IIncludableQueryable EF.Property method can't locate sub properties. For example;
DataTables.CreateResponse<Rayon>(context.Rayons.Include(p=>p.User), parameters);
EF.Property<T>.Property<string>(p, "Name") is working but, EF.Property<T>.Property<string>(p, "User.Name") is not working, exception message is "EF.Property called with wrong property name."
Sorry for bad English.

How to assign values from storage to a variable in ionic 3

I tried few methods to assign values to variable but could succeed please help.
Method 1:-
getData() {
return this.storage.get('products')
.then(res => {
return this.cart = res;
});;
}
Console.log shows undefined
Method 2:-
cart = [];
getData() {
return this.storage.get('products')
.then(res => {
return this.cart.push(res);
});;
}
Output :
How can i achieve
Cart variable as directly the array list from 0, 1,? [as shown in picture]
Found the Solution
//set Cart Storage
this.storage.get('products').then((data) => {
if (data == null) {
data = [];
}
this.cart = data;//re-initialize the items array equal to storage value
this.cart.push(this.cartItem());
this.storage.set('products', this.cart);
console.log("Cart" + this.cart);
});
On Another Page
// Retrieving data
public getData() {
return this.storage.get('products')
.then(res => {
this.cart = [];
this.cart = res;
console.log(this.cart);
});
}
Try logging the value of the res parameter in the console. From there, you can assign the value of cart to the correct property in the res object.

Ionic 2 search bar

I'm implementig a search bar, it filters the way I want, but after 2 seconds, it shows the whole array again, and I dont really understand why.
Thanks for your help.
This is the .ts
getCatalog() {
this.http.get('url', {}, {}).then(data => {
console.log("Data:", JSON.parse(data.data));
this.catalogList = JSON.parse(data.data);
// console.log(data.status);
// console.log(data.data); // data received by server
// console.log(data.headers);
})
.catch(error => {
console.log(error.status);
console.log(error.error); // error message as string
console.log(error.headers);
});
}
getItems(ev: any) {
// Reset items back to all of the items
this.getCatalog();
// set val to the value of the searchbar
let val = ev.target.value;
//console.log("VALUE", ev);
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.catalogList = this.catalogList.filter((item) => {
console.log("ITEM", item)
return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
This is where i have the *ngFor
<ion-searchbar (ionInput)="getItems($event)"></ion-searchbar>
<ion-grid>
<ion-row *ngFor="let item of catalogList">
Other code here
I think the problem is that your HTTP request finishs after you've already filtered your array, this'll make the catalogList receive the parsed JSON after you've filtered, this is why it resets.
Do you really need to get your catalog from the server every time the ser types something in the searchbar? Is your catalog that dynamic? If not you can simply save it in your catalogList when the user enters the page and create another object to be used at your filter:
public catalogListFiltered: any[] = []; // CREATE A NEW VARIABLE THAT'LL BE USED ON YOUR NGFOR
ionViewDidEnter() { // or ionViewDidLoad, depends on what lifecycle you need
this.http.get('url', {}, {}).then(data => {
this.catalogList = JSON.parse(data.data);
this.initializeCatalogs();
});
}
// THIS'LL SET YOUR FILTERED ARRAY TO THE FIRST/FULL VERSION OF YOUR CATALOG
initializeCatalogs(){
this.catalogListFiltered = this.catalogList;
}
getItems(ev: any) {
// Reset items back to all of the items
this.initializeCatalogs();
// set val to the value of the searchbar
let val = ev.target.value;
//console.log("VALUE", ev);
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.catalogList = this.catalogList.filter((item) => {
console.log("ITEM", item)
return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
If you really need to call your API everytime to get your catalog just work with promises
getCatalog = (): Promise<any> {
return new Promise<any>(resolve => {
this.http.get('url', {}, {}).then(data => {
resolve(JSON.parse(data.data));
});
});
}
// maybe this'll have the same effect as the above, maybe someone can say if that'll work with some changes on your 'getItem' method:
// getCatalog(){ return this.http.get('url', {}, {}); };
getItems(ev: any) {
// Reset items back to all of the items
this.getCatalog().then(res => {
this.catalogList = res;
// set val to the value of the searchbar
let val = ev.target.value;
//console.log("VALUE", ev);
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.catalogList = this.catalogList.filter((item) => {
return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
});
}
Hope this helps.