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

Dynamically filter a single view/mappings from full-text search results with inter-dependent results #530

Open
king7532 opened this issue Sep 24, 2020 · 0 comments

Comments

@king7532
Copy link

king7532 commented Sep 24, 2020

I'm using the YapDatabaseFullTextSearch extension to index and search all my user data, Contacts and Notes, see below. They are in separate collections, and only Notes has a property to reference its Contact ID. In the main user interface, I have a YapDatabase view and mappings to show all the Contacts. And I have a search controller to search all the Contacts and Notes. I want to dynamically filter only all the contacts view/mappings as the user searches, and only show the contacts for which there are search results in either Contacts or Notes. I do not want to show the Notes, only the Contact that is associated with the Note in the search results.

///// Data models
struct Contact {
    var id: String
    var name: String
}

struct Note {
    var id: String
    var contactID: String   // A contact can have many notes
    var text: String
}

Currently, in may SearchResultsViewController, I have rigged up a YapDatabaseFilteredView that is updated (by incrementing the versionTag) as the user types a search query, see performSearch below. What is the best way to dynamically filter a view/mappings? Any help or advice will be greatly appreciated. Thank you.

func performSearch(_ query: String) {
        
        filteredContacts.removeAll()   // A `Set<String>` of all the filtered contact IDs
        
        dbConnection.read { transaction in
            guard let ftsTransaction = transaction.ext("contacts_notes_fts") as? YapDatabaseFullTextSearchTransaction,
                  let filterTransaction = transaction.ext("filteredSearchContacts") as? YapDatabaseFilteredViewTransaction
            else { return }
            
            let options = YapDatabaseFullTextSearchSnippetOptions()
            ftsTransaction.enumerateKeysAndObjects(matching: query, with: options) { snippet, collection, key, object, stop in
                if let contact = object as? Contact {
                    self.filteredContacts.insert(key)
                } else if let note = object as? Note {
                    self.filteredContacts.insert(note.contactID)
                }
                os_log("filteredContacts.count: %d", self.filteredContacts.count)
            }
        }

        searchConnection.readWrite { transaction in
            guard let filterTransaction = transaction.ext("filteredSearchContacts") as? YapDatabaseFilteredViewTransaction
            else { return }
            SearchResultsViewController.FilterVersion += 1  // You need to update the versionTag or it won't run your filter closure `self.filtering`
            filterTransaction.setFiltering(self.filtering, versionTag: String(SearchResultsViewController.FilterVersion))
        }
    }
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