Skip to content
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

SQL queries for enumerating edges (relationships) - How many queries are executed? #528

Open
SwiftedMind opened this issue Jul 26, 2020 · 0 comments

Comments

@SwiftedMind
Copy link

Hey,

I've just found this framework and I really love it so far. It seems to be amazing. I have one (possibly very simple) question about the performance of enumerating relationship edges. I've tried looking through the code but I don't really understand everything that's happening under the hood. And I've read through the wiki and I don't think it's explicitly mentioned there.

In the wiki, under "Querying for Edges" (https://github.com/yapstudios/YapDatabase/wiki/Relationships#querying-for-edges), there is this code example:

var numbers: [PhoneNumber] = [];
dbConnection.read {(transaction) in
  
  guard
    let contact = transaction.object(forKey: contactId, inCollection: "contacts") as? Contact,
    let relationshipTransaction = transaction.ext("relationships") as? YapDatabaseRelationshipTransaction
  else {
    return
  }
    
  relationshipTransaction.enumerateEdges(withName: "number"
                                        sourceKey: contactId
                                       collection: "contacts") {
    (edge, stop) in
    
    if let number = transaction.object(forKey: edge.destinationKey, inCollection: edge.destinationCollection) as? PhoneNumber {
      numbers.append(number)
    }
  }
}

My question is: Does the enumerateEdges(...) method already fetch all objects from the database so that a later call to transaction.object(...) just grabs it from the cache or something?

Or does each call to transaction.object(...) trigger an SQL query?

Also, I have one more related question:
Assuming that enumerateEdges(...) already caches all edges, would it be possible to efficiently use linked lists to store the order of the objects?

What I mean by that is: In the example above, we want to query all phone numbers for a given contact. I want to somehow store the order of the phone numbers inside the database (so that the user can arbitrarily move them). And I want to this by linking the objects together with nextId, and previousId properties, pointing to the respective successor/predecessor. A PhoneNumber struct could look like this:

struct PhoneNumber: Codable {
  ...
  var previousId: UUID? // Id of the next phone number, if there is one
  var nextId: UUID? // Id of the previous phone number, if there is one
  ...
}

To get all phone numbers in the correct order you just have to start with the phone number that doesn't have a previousId pointer (either by searching for it or storing it somewhere) and iterate through all successive objects using nextId.

Assuming that all edges are already in the cache (from the enumerateEdges(...) call earlier), this process should be pretty fast, right?

If all of this is actually as I think it is, then my follow-up question would be: Is there a more elegant solution to this? The enumerateEdges(..) method accepts a closure that is called for each edge that has been found. Using this linked list approach, I would just leave this closure empty, because the order isn't correct. Is there a way to "fetch" all edges without explicitly iterating them? Or should I just use an empty closure?

Thanks for any help! I really appreciate it, this framework is awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant