-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Entity: adapter.addOrUpdate #421
Comments
This should be added for many entities as well: |
This is called "Upsert" in some databases. There could also be call for "Replace", which would Add or replace rather than than Add or merge; this would be important if, for example, an entity with an optional field has that field unset (and not returned by the server). |
+1, though another possible workaround is to simply compose the reductions: case user.ADD_OR_UPDATE: {
const changes = action.payload.user;
const id = changes.id;
state = adapter.addOne({ id, changes }, state); // safe, either create or do nothing
return adapter.updateOne(changes, state); // also safe, now it exists, we apply a (possibly dummy) update
} Obviously, a more native check would avoid additional calculations. |
Adding |
Btw, in platform/modules/entity/src/unsorted_state_adapter.ts Lines 71 to 90 in aa7172a
indexOf when index only has to be used if the id has changed (and the check for index === -1 can be easily replaced with !(update.id in state.entities) )? It may be wise to move it inside if (newKey !== update.id) { to avoid possible quadratic time penalty when calling updateOneMutably from updateManyMutably .
Same goes for @jobvanstiphout's comment above - if we are to implement upsertOne, we need to make sure not to unnecessarily call |
Also, calling
N log N by sorting the "new" array and then copy-merging it with the "old" one (which is already sorted).
|
@dinvlad I will gladly accept PRs that improve perf 👍 |
sounds good, I can take a look into it |
I've updated methods to improve performance of collection operations. Let me know if you'd consider a PR for upserts too. |
Sure |
I would suggest "upsert" instead of "addOrUpdate". First many db systems do so and seconds it sounds better to say "upsertMany" instead of "addOrUpdateMany". It is definitly a must have for the adapter! |
I agree with @xipheCom . |
Sorry got a bit distracted, can draft it over the weekend |
Any progress @dinvlad ? |
Submitted a PR. Sorry for the delay. I kept the signature for |
More specifically,
So to use export type Update<T> = {
id: string | number;
changes: Partial<T>;
}; |
But then we won't be able to change |
we should use the signature of Update for Upsert. If we think in a Database System update and upsert have both a query. They are very similar. An Insert (or Add) function has another task. Add: Add something I think you have done it right! Any idea of the team when the PR will be accepted? |
Nice work on the PR @dinvlad. One issue I can see with keeping the
Changing the signature to be the same as Add would a good alternative. |
Hmm, one thing I've just realized is that the current PR (and test fixtures) don't take into account the situation when platform/modules/entity/src/unsorted_state_adapter.ts Lines 130 to 133 in 9826793
But if the effective id is named differently (e.g. selectId = entity => entity.title ), then this simple approach will fail.
|
Or as @georgeF105 noted, we can use function upsertManyMutably(updates: FullUpdate<T>[], state: R): boolean;
...
if (update.id in state.entities) {
updated.push(update);
} else {
// now each change must be a full entity
// containing the new effective id.
added.push(update.changes);
} That will enable complete replacement of an entity, including its effective id, and will prevent addition of partial entities. |
@dinvlad Thank you for your work on this. I'm about to refactor a pretty giant redux mess and I'm wondering if a merge is on the horizon? Your point about needing to respect the defined |
I'm submitting a...
What is the current behavior?
Sometimes when receiving a full entity from the server, you don't know if it already exists. At the moment you need to check for that manually and choose to update instead of add.
Expected behavior:
The adapter provides a method that adds the entity when it does not exists, but merges (or replaces as it's not a partial entity) the entity into the existing one when it does exist.
The text was updated successfully, but these errors were encountered: