I am trying to figure out how to create and delete nodes with Relay where I don't have a parent node. It seems that NODE_DELETE/RANGE_DELETE and RANGE_ADD all require a parent node. Is there a way to perform create and delete mutations from the root query object in Relay.js?
Note: I did find example where creates can be performed with a FIELDS_CHANGE query, but they lack any documentation or reason.
You should be able to use REQUIRED_CHILDREN for this purpose. It's not currently well-documented (or even documented), and it has a somewhat confusing name (as a result, we have a task for renaming it and improving the docs). It will likely be renamed to EXTRA_FRAGMENT in the future.
Normally when you issue a mutation, we perform an intersection between the "fat query" (all the fields that could possibly change as the result of the mutation) and the "tracked query" (all the fields that your app has requested for a node so far, and which should be updated when they change) and we send this query to the server with the mutation.
So, for the use case of creating an entirely new node with no parent, you can specify an identifying field like id in the REQUIRED_CHILDREN, and then use that to, for example, navigate to a view showing the newly-created object. This answer has a very detailed example of how you would do this.
You can pass client:root as the parentID. And then your pathToConnection would be ['client:root', 'someConnection'].
(Tested with Relay Modern. Not sure if this also applies to Relay Classic, but that's officially deprecated now anyways. But this is still one of the top Google results for this issue, so answering.)
(Found in this GitHub issue)
Related
How can I invalidate a single item when working with useInfiniteQuery?
Here is an example that demonstrates what I am trying to accomplish.
Let`s say I have a list of members and each member has a follow button. When I press on to follow button, there is a separate call to the server to mark that the given user is following another user. After this, I have to invalidate the entire infinite query to reflect the state of following for a single member. That means I might have a lot of users loaded in infinite query and I need to re-fetch all the items that were already loaded just to reflect the change for one item.
I know I can change the value in queryClient.setQueryData when follow fetch returns success but without following this with invalidation and fetch of a member, I am basically going out of sync with the server and relying on local data.
Any possible ways to address this issue?
Here is a reference UI photo just in case if it will be helpful.
I think it is not currently possible because react-query has no normalized caching and no underlying schema. So one entry in a list (doesn't matter if it's infinite or not) does not correspond to a detail query in any way.
If you prefix the query-keys with the same string, you can utilize the partial query key matching to invalidate in one go:
['users', 'all']
['users', 1]
['users', 2]
queryClient.invalidateQueries(['users]) will invalidate all three queries.
But yes, it will refetch the whole list, and if you don't want to manually set with setQueryData, I don't see any other way currently.
If you return the whole detail data for one user from your mutation, I don't see why setting it with setQueryData would get you out-of-sync with the backend though. We are doing this a lot :)
I have a situation where, in a model's afterSave callback, I'm trying to access data from a distant association (it's a legacy data model with a very wonky association linkage). What I'm finding is that within the callback I can execute a find call on the model, but if I exit right then, the record is never inserted into the database. The lack of a record means that I can't execute a find on the related model using data that was just inserted into the current.
I haven't found any mention of when data is actually committed with respect to when the afterSave callback is engaged. I'm working with legacy code, but I see no indication that we're specifically engaging transactions, so I'm trying to figure out what my options might be.
Thanks.
UPDATE
The gist of the scenario is this: We're taking event registrations, but folks can be wait listed. A user can register (or be registered) for a given Date. After a registration is complete, I need to check the wait list for the existence of a record for the registering user (WaitList.user_id) on the date being registered for (WaitList.date_id). If such a record exists, it can be deleted because it's become an active registration.
The legacy schema puts me in a place where the registration isn't directly tied to a date so I can't get the Date.id easily. Instead, Registration->Registrant->Ticket->Date. Unintuitive, I know, but it is what it is for now. Even better (sarcasm included), we have a view named attendees that rolls all of this info up and from which I would be able to use the newly created Registration->id to return Attendee.date_id. Since the record doesn't exist, it's not available in the view.
Hopefully that provides a little more context.
What's the purpose of the find query inside of your afterSave?
Update
Is it at all possible to properly associate the records? Or are we talking about way too much refactoring for it to be worth it? You could move the check to the controller if it's not possible to modify the associations between the records.
Something like (in psuedo code)
if (save->isSuccessful) {
if (onWaitList) {
// delete record
}
}
It's not best practice, but it will get you around your issue.
in my application ( kind of wiki clone ) - an article is frequently changing.
and i need to track all changes that are done on that article. { text only. }
one crude way i have done it, is to add a datetime property and create a new entity everytime something change. which is too much database wasting. { and also un-necessary index waste too. } and also need to re-create parent-child and entity relationships.
i also have log which can show changes -- but i want some thing easier , so that jumping from one version to another version could be easier.
ideas ?
thanks.
You could split the location in your wiki from the content, and link from there to the version of the page. Keep the versions in a linked list, doubly linked if you 2 way navigation, circular, whatever.
The parent child, indexing and so forth deal only with the location and the article linked to that.
Reverting to a previous change is only changing the link in the location (and pushing the changes to your indexing machine). Pruning are basic list operations, i.e. pointing the next field to a version further down and deleting the version in between.
Google is proposing changing one entry at a time to the default values ....
http://code.google.com/appengine/articles/update_schema.html
I have a model with a million rows and doing this with a web browser will take me ages. Another option is to run this using task queues but this will cost me a lot of cpu time
any easy way to do this?
Because the datastore is schema-less, you do literally have to add or remove properties on each instance of the Model. Using Task Queues should use the exact same amount of CPU as doing it any other way, so go with that.
Before you go through all of that work, make sure that you really need to do it. As noted in the article that you link to, it is not the case that all entities of a particular model need to have the same set of properties. Why not change your Model class to check for the existence of new or removed properties and update the entity whenever you happen to be writing to it anyhow.
Instead of what the docs suggest, I would suggest to use low level GAE API to migrate.
The following code will migrate all the items of type DbMyModel:
new_attribute will be added if does not exits.
old_attribute will be deleted if exists.
changed_attribute will be converted from boolean to string (True to Priority 1, False to Priority 3)
Please note that query.Run returns iterator returning Entity objects. Entity objects behave simply like dicts:
from google.appengine.api.datastore import Query, Put
query = Query("DbMyModel")
for item in query.Run():
if not 'new_attribute' in item:
item['attribute'] = some_value
if 'old_attribute' in item:
del item['old_attribute']
if ['changed_attribute'] is True:
item['changed_attribute'] = 'Priority 1'
elif ['changed_attribute'] is False:
item['changed_attribute'] = 'Priority 3'
#and so on...
#Put the item to the db:
Put(item)
In case you need to select only some records, see the google.appengine.api.datastore module's source code for extensive documentation and examples how to create filtered query.
Using this approach it is simpler to remove/add properties and avoid issues when you have already updated your application model than in GAE's suggested approach.
For example, now-required fields might not exist (yet) causing errors while migrating. And deleting fields does not work for static properties.
This doesn't help OP but may help googlers with a tiny app: I did what Alex suggested, but simpler. Obviously this isn't appropriate for production apps.
deploy App Engine Console
write code right inside the web interpreter against your live datastore
like so:
from models import BlogPost
for item in BlogPost.all():
item.attr="defaultvalue"
item.put()
Using parent child relationship where a parent can have children while each child has only one parent, does using Children.all().ancestor(parent.key) a good solution where a child is constructed by setting parent=parent.key in the constructor? Is the 1000 limit applies with this kind of query?
The query returns what you'd expect, all Children which have the specified parent anywhere in their ancestry. The query expresses exactly that, so I doubt there's a simpler way of doing the same thing. But App Engine does keep adding features and surprising me :-)
Possibly you need parent.key(), I think it depends whether you're in Python or Java.
Btw, it's not recommended to use ancestor-parent-child to model relationships in your data. Entity groups exist to enable transactions, not for use as a "free" ReferenceProperty. parent-child should be a low-level implementation detail, meaning either "these two entities may need to be modified in a single transaction", or perhaps "I am playing an optimization trick which allows me to use list properties without having to load the list into memory when I get the entity". As a rule of thumb, if the entities don't all "belong" to the same user, then they shouldn't be parent-child related, because relating them in that way introduces contention when different users try modify them via different datastore nodes:
http://code.google.com/appengine/docs/python/datastore/keysandentitygroups.html#Entity_Groups_Ancestors_and_Paths
Another way to get descendants (children) of a parent entity in Google App Engine that I just discovered:
childrenEntities = db.query_descendants(parentEntity).fetch(1000)
Not sure if it will be helpful to you. It was helpful to me because I was having difficulty figuring out how to access the child class(es) which were created with a python module I installed.
As others have indicated elsewhere, the 1000 limit for everything was removed in February 2010. See the linked blog entry for more details re: this.