Optimizing Parse to query for new objects - ios

I am using Parse as the backend for an app I'm working on. I was wondering if there is an optimal algorithm to query for only 'unseen' new objects.
What I am planning on doing is something like adding a user to the viewed object's relation and later querying all objects to check for the absence of the user. This seems to be O(n* all users who have seen an 'n') complexity which is a bit too much.
Another way to do this is to add the object to a user's key 'seen' and to then query for all objects the user has not seen.
Maybe a much more efficient way could be (assuming I view these objects chronologically) is to mark the first and last objects I see, and only show ones before or after those points using the createdAt key. Then I guess to show new objects outward from those points to not have to divide into multiple queries.
Ideally I'd like to shuffle through the objects, but I also would like to keep this algorithm as efficient as possible.

Create a Class called View. Each View consists of a unique identifier from a viewable Object (CANNOT BE THE OBJECTID) and a pointer to the User that viewed the object.
Your query should be:
//(Simple equalTo query)
Query1 = All View Objects where User pointer = User
//(whereKey:that-unique-id-column doesNotMatchKey:that-unique-id-column inQuery:Query1)
Query2 = All viewable Objects where not included in pointers in Query1

Related

Querying Firebase Firestore Data

I'm looking to build an app that functions like a dating app:
User A fetches All Users.
User A removes Users B, C, and D.
User A fetches All Users again - excluding Users B, C, and D.
My goal is to perform a query that does not read the User B, C, and D documents in my fetch query.
I've read into array-contains-any, array-contains, not-in queries, but the 10 item limit prevents me from using these as options because the "removed users list" will continue to grow.
2 workaround options I've mulled over are...
Performing a paginated fetch on All User documents and then filtering out on the client side?
Store all User IDs (A, B, C, D) on 1 document in an array field, fetch the 1 document, and then filter client side?
Any guidance would be extremely appreciated either on suggestions around how I store my data or specific queries I can perform.
You can do it the other way around.
Instead of a removed or ignored array at your current user, you have an array of ignoredBy or removedBy in which you add your current user.
And when you fetch the users from the users collection, you just have to check if the requesting user is part of the array ignoredBy. So you don’t have tons of entries to check in the array, it is always just one.
Firestore may get a little pricey with the Tinder model but you can certainly implement a very extensible architecture, well enough to scale to millions of users, without breaking a sweat. So the user queries a pool of people, and each person is represented by their own document, this much is obvious. The user must then take an action on each person/document, and, presumably, when an action is taken that person should no longer reappear in the user's queries. We obviously can't edit the queried documents because there could be millions of users and that wouldn't scale. And we shouldn't use arrays because documents have byte limits and that also wouldn't scale. So we have to treat a collection like an array, using documents as items, because collections have no known limit to how many documents they can contain.
So when the user takes an action on someone, consider creating a new document in a subcollection in the user's own document (user A, the one performing the query) that contains the person's uid, and perhaps a boolean to determine if they liked or disliked that person (i.e. liked: true), and maybe a timestamp for UI purposes. This new document is the item in your limitless array.
When the user later performs another query, those same users are going to reappear in the results, which you need to filter out. You have no choice but to check if each person's uid is in this subcollection. If it is, omit the document and move to the next. But if your UI is configured like Tinder's, where there isn't a list of people to scroll through but instead cards stacked on top of each other, this is no big deal. The user will only be presented with one person at a time and they won't know how many you're filtering out behind the scenes. With a paginated list, the user may see odd behavior like uneven pages. The drawback is that you're now paying double for each query. Each query will cost you the original fetch and the subcollection-check fetch. But, hey, with this model you can scale to millions of users without ever breaking a sweat.

SharkORM - How to parse results of Joins

I am trying to use SharkORM to fetch relationships across my objects. I am familiar with the joinTo syntax defined in SharkORM's documentation, but I am not sure how to use the resulting joinedResults object to get the related objects I need.
[[Person query] joinTo:[Department class] leftParameter:#"department" targetParameter:#"Id"]
outputs
{
"Department.Id" = 61;
"Department.location" = 35;
"Department.name" = Development;
}
into the Person.joinedResults field, but how do I take those results and get a Department object back. I've tried making a call to person.department after the joinTo, but it seems to make a second query to the database as if I hadn't used joinTo at all.
Am I really expected to parse the dictionary results of person.joinedResults into a Department object manually? That is very cumbersome, especially when you start joining more than one relationship.
I feel as if I am missing some obvious way to use the results of the joinTo.
The join functionality is in addition to relationships. So you can reference unrelated (or related) tables in a query, but then objects you get back can only ever be physically structured as per your original class, and are defined from the data and not from your query.
So, in a nut shell; joinTo: will enable you to reference remote or unrelated objects in your query for selection.
But to traverse object relationships you would use the properties.
Person* p = GetFirstPerson()
// reference/traverse the object to look at relationships (1:1)
p.department
or
p.department.location
So I guess what i'm saying is, even though it is SQL like syntax, you can only ever end up with rigidly defined classes in a fixed structure as a result unless using other interfaces such as sum, distinct etc..

With Realm, should I use a List object or Results object as the data source for a UITableView?

There are at least 2 main collection types used in Realm:
List
Results
The relevant description from the documentation on a Results object says:
Results is an auto-updating container type in Realm returned from
object queries.
Because I want my UITableView to respond to any changes on the Realm Object Server, I really think I want my UITableView to be backed by a Results object. In fact, I think I would always want a Results object to back my UI for this reason. This is only reinforced by the description of a List object in the documentation:
List is the container type in Realm used to define to-many
relationships.
Sure seems like a List is focused on data modeling... So, being new to Realm and just reading the API, I'm thinking the answer is to use the Results object, but the tutorial (Step 5) uses the List object while the RealmExamples sample code uses Results.
What am I missing? Should I be using List objects to back my UITableViews? If so, what are the reasons?
Short answer: use a List if one already exists that closely matches what you want to display in your table view, otherwise use a Results.
If the data represented by a List that's already stored in your Realm corresponds to what you want to display in your table view, you should certainly use that to back it. Lists have an interesting property in that they are implicitly ordered, which can sometimes be helpful, like in the tutorial you linked to above, where a user can reorder tasks.
Results contain the results of a query in Realm. Running this query typically has a higher runtime overhead than accessing a List, by how much depends on the complexity of the query and the number of items in the Realm.
That being said, mutating a List has performance implications too since it's writing to the file in an atomic fashion. So if this is something that will be changing frequently, a Results is likely a better fit.
You should use Results<> as the Results is auto updating to back your UITableView. List can be used to link child models in a Realm model. where as Results is used to query the Realm Objects and you should add a Realm Notification Token so you know when the Results are updated and take necessary action (reload table view etc.) Look here for realm notifications: https://realm.io/docs/swift/latest/#notifications
P.S. The data in that example is just static and no changes are observed

Realm: Query for objects with same property

Is it possible in realm to query for objects that have the same property value?
Imagine a list of contacts with firstname and lastname. I want to query all contacts that have the same name and may be duplicates in the db.
As far as I'm aware, there's no automatic way to do that with NSPredicate (Of which Realm implements); it would need to be done manually.
That being said, it should be relatively trivial to do manually; simply loop through each object, performing a query that searches for that object's name properties, and see if the number of results returned is greater than 1.
That being said, depending on how big your data set is, this could become a very slow operation very quickly. Ideally, you might be better off ensuring that duplicate entries don't occur, or if they do, to somehow index them so they're easier to look up.

Storing object as property in Neo4j

I need to store an array of User objects inside a Tile node. Each User object contains three primitive properties; Id(a single alpha-character string) , fName and lName. This list of objects is a property of the Tile node with several other primitive properties. The entire Tile node needs to be serialized to Json, including the nested User objects.
I understand that Neo can't store complex objects as properties. I created the User as a separate node with id, fName and lName as properties, and I can get these returned via Cypher. I can also get Json output results for the parent Tile node. (In this case, Users is just a string of comma-separated alphas). But how do I get the User node output nested inside the parent node?
I have created a list of User objects (userList) by relating user objects with the string of user ids in the Tile Node via a Cypher Query. I just need to get from two separate json outputs to a single nested output.
I hope this is enough detail. I'm using Neo4j 2.1.6 and Neo4jClient. I'm also using .Net 4.0.
You could do something like this with cypher and have the cypher return a composite object.
MATCH (t:Tile)-[:CONTAINS_USER]-(u:User)
WHERE t.name =~ 'Tile.*'
WITH {name: t.name, users: collect(u) } AS tile
RETURN collect(tile) AS tiles
You shouldn't store another object as a nested property. As you correctly state, neo4j doesn't support that but even if it did, you shouldn't do it, because you should link the two with a relationship. That's the key strength of a graph database like neo4j, so you should play to that strength and use the relationships.
The server has a default JSON format that tends to output nodes as their own JSON objects. That means that practically speaking, since you're going to model this as two separate nodes with a relationship, you can't get the server by default to nest the JSON for one object underneath of the other. It won't nest the JSON that way because that's not how the data will be stored.
In this case, I'd use the REST services to fetch the JSON for each object individually, and then do the nesting yourself in your code -- your code is the only place where you'll know which property it should be nested under, and how that should be done.
In addition to these answers, note that if you don't need to involve the subfield properties in any of your queries (e.g. search for Tiles where a User.name is "X"), you can simply serialise the objects fields to a string before insertion (e.g. with JSON.stringify), and unserialise them when reading from the DB.
This is especially useful when you want to "attach" structured data to a node, but that you don't much care about this data with regards to the relations in your DB (e.g. User preferences).

Resources