I am creating a Google App Engine app that has a kind of User-Timeline in it (as in Facebook or Twitter), which consists of series of events sorted chronologically, using the Datastore.
However, I'm unable to come up with some efficient way.
In present solution, i define an entity as:
Entity:Activities:-
- Id
- Details...
- ...
- Timestamp
Is this a way so that i can index and get the activities in some sorted order, according to Timestamp ?
I am working with Java and using Objectify for data access.
The rule is : if you you want to query/order using a property, you need to index it.
I think it's pretty straight forward, what you're doing works.
The question is : what else do you want ? is performance a major need ? (probably, since your app seems user oriented).
If you only need to log user activities and retrieve it, I might suggest that you put your "Activity" entity under a parent entity "User" or "UserActivity".
UserActivity (key name = user id)
Activity (id, details, timestamp [indexed])
That way you will be able to run ancestor queries using your user's ID to retrieve all his posts.
The only drawback is that it will limit you to one write per second on this entity group (basically "all the user activity").
Related
I have search a lot on stackoverflow and read many questions
I was having 3 indexOn problem 2 of them are solved and 1 remains
I am sorting database and have indexOn on "favorite" and "poet" which runs successfully but I need one more indexOn for numbers inside heart node.
query is running successfully but I am getting indexOn warning in android studio
I have tried using variables in place of numbers in database rule but still getting warning
Using an unspecified index. Your data will be downloaded and filtered on the client. Consider adding '".indexOn": "heart/+91916*******"' at gazal to your security and Firebase Database rules for better performance
queryFav = FirebaseDatabase.getInstance()
.getReference(reference).orderByChild(child).equalTo("heart");
above query run successfully but what should be indexOn rule
The message you get means you are running a query that has orderBy("heart/+91916*******") on a node named gazal. To efficiently run that query, you need to have an index on heart/+91916******* to that node in your security rules. But since the +91916******* part of that index probably is dynamic (i.e. you'll have a different value of +91916******* for every user of the app), you'll have to add an index for each user. That is not feasible.
In other words: you current data structure makes it easy to read the users who have hearted a specific poem. It does however not make it easy to determine the poems that a specific user has hearted. To make that equally easy, you'll want to add an additional data structure"
"user_hearts": {
"+91916*******": {
"-KjYiXzl1ancR8Pi3MfQ": true
}
}
With the above structure you can easily read the user_hearts node for the user you're interested in, and then read the poems one by one if needed.
Also see:
Firebase query if child of child contains a value
Firebase Realtime Database - index on location containing uid
Let's say you have a database table name table1 with columns name and surname. Two different clients open the same view from the java application and get the data for same person at the same time.
1) First client changed the name and pressed save button to update database record.
2) Client2 still sees the old record on the screen and then pressed to save button to change the surname.
It actually overwrite the record by old name. I think to check and get the latest data before updating the database when I click button but I do not like this solution because of making a second query before update.
So how can we solve this problem by using Hibernate and without using Hibarnete. Any idea?
Of course if you do not want that something will be overridden, then you have to check the data before an update. But it will be not always a real query with a good caching strategy. You could also use a timestamp with last update to compare it easier. Another strategy would be to lock the entities when the first user will read them. But that is normally not a good design for web applications or you have to integrate a messaging service, which will all user inform for an update who actually have open that entity. But I think that is not so easy to implement and a more advanced feature.
In short, compare the timestamp of an entity and if already updated, then compare the changes and show them for the user who wanted update that entity.
I am just starting off with app development and am currently writing an Android application which has registered users and a list of 'challenges' which they are able to select and later mark as completed/failed.
The plan is to eventually store all users/challenge/etc data on a database though I haven't implemented this yet.
The issue I have run in to is this - in my current design each User has list variables containing their current challenges and completed challenges eg. two ArrayList fields.
Users currently select challenges from a listview of different Challenge objects, which are then added to the user's CurrentChallenges list.
What I had not accounted for is how to structure this so that when a user takes on a challenge, they have their own unique copy of that challenge that can be independently marked as completed etc, whereas at the minute every user that selects say, Challenge 1, is simply adding the same challenge with the same ID etc. as each other user that selects Challenge 1.
I supposed I could have each different challenge be its own sub-class of Challenge and assign every user which selects that challenge type a different instance of that class, however this seems like it would be a very messy/inefficient method as all the different classes would be largely the same.
Does anyone have any good ideas or design patterns for this case? Preferably a solution that will be compatible with later storing these challenges in a database and presumably using ORM.
Thanks a lot for any suggestions,
E
I'd move every aspect of a challenge that is different for each user into a new Attempt class. So Challenge might have variables for name, description etc. and Attempt would have inProgress, completed etc. Obviously these are just examples, replace them with whatever data you're actually storing.
Now in your User class, you can record challenges using a Map. Make it a Map<Challenge, Attempt> and each User will be able to store an Attempt for each Challenge to record their progress. The Challenge instances are shared between users but there is an Attempt instance for each combination of User and Challenge.
When you implement the database later, Challenge, User and Attempt would each translate to a table. Attempt would have foreign keys for both of the other tables. Unfortunately I haven't used ORMs much so I'm not sure whether they'd work with a Map correctly.
I'm trying to delete a record from the GAE datastore via an ajax query which sends the object "primary key" (Long Id with auto increment).
Currently, I'm doing this (hard coded the key=6):
Objectify ofy = ObjectifyService.begin();
ofy.delete( Test1.class , 6);
This works : it deletes the entity which has the Key=6.
But for security reasons, I need another parameter (fyi : "parent_user") so only the owner can delete this object.
It seems Objectify.delete() doesn't allow to pass more parameters than the key...
How could I solve this ? Because making a Objectify.get() with my optional parameters+key to get the full object then sending the whole object to the delete() is nubish & unoptimized...
As presented at http://objectify-appengine.googlecode.com/svn/trunk/javadoc/index.html, Objectify.delete() does not take any additional parameters besides object keys, ids, or strings.
So, you need to first get the object based on your filters and then delete them. However, in order to optimize this, you can get only the key of the object and not the full object. Then you delete based on the key.
Hope this helps!
If your data model allows you to let the user be the Datastore ancestor of your objects, you can get rid of the query, since the ancestor is part of the key.
What I often do is to authenticate the user in the beginning of every request, which uses the #Cached annotation of Objectify to cache all users (and their privileges, which are embedded into the user).
Then, most of the user related data has the user as the ancestor. This way, whenever a user tries to access or delete a resource, I will never accidently allow the user to do it on any objects that isn't hers. All-in-all, only gets which are quick and cachable.
It is advisable to store some information(meta-data) about a content in the Id(or key) of that content ?
In other words, I am using a time based UUIDs as the Ids (or key) for some content stored in the database. My application first accesses the list of all such Ids(or keys) of the content (from the database) and then accessed the corresponding content(from the database). These Ids are actually UUIDs(time based). My idea is to store some extra information about the content, in the Ids itself, so that the my software can access this meta-content without accessing the entire content from the database again.
My application context is a website using Java technology and Cassandra database.
So my question is,
whether I should do so ? I am concerned since lots of processing may be required (at the time of presentation of data to user) in order to retrieve the meta data from the ids of the content!! Thus it may be instead better to retrieve it from database then getting it through processing of the Id of that content.
If suggested then , How should I implement that in an efficient manner ? I was thinking of following way :-
Id of a content = 'Timebased UUID' + 'UserId'
where, 'timebasedUUID' is the generated ID based on the timestamp when that content was added by a user & 'userId' represents the Id of the user who put that content.
so my example Id would look something like this:- e4c0b9c0-a633-15a0-ac78-001b38952a49(TimeUUID) -- ff7405dacd2b(UserId)
How should I extract this userId from the above id of the content, in most efficient manner?
Is there a better approach to store meta information in the Ids ?
I hate to say it since you seem to have put a lot of thought into this but I would say this is not advisable. Storing data like this sounds like a good idea at first but ends up causing problems because you will have many unexpected issues reading and saving the data. It's best to keep separate data as separate variables and columns.
If you are really interested in accessing meta-content with out main content I would make two column families. One family has the meta-content and the other the larger main content and both share the same ID key. I don't know much about Cassandra but this seems to be the recommended way to do this sort of thing.
I should note that I don't think that all this will be necessary. Unless the users are storing very large amounts of information their size should be trivial and your retrievals of them should remain quick
I agree with AmaDaden. Mixing IDs and data is the first step on a path that leads to a world of suffering. In particular, you will eventually find a situation where the business logic requires the data part to change and the database logic requires the ID not to change. Off the cuff, in your example, there might suddenly be a requirement for a user to be able to merge two accounts to a single user id. If user id is just data, this should be a trivial update. If it's part of the ID, you need to find and update all references to that id.