Realm query to exclude results from relations - ios

I have
class Person: Object {
let friends = List<Person>()
let family = List<Person>()
}
I have person instance, which includes links to some other persons in person.friends list.
And I want to query all other Person objects, not including person.friends and person.
I can make two for in loops to check if the query doesn't contain persons from the list, but it seems like not the best way to do that.
P.S. In CoreData I did it with predicate:
let predicate = NSPredicate(format: "SELF != %# AND NOT SELF IN %#",person, person.friends),
But Realm gives me an error:
Predicate expressions must compare a keypath and another keypath or a
constant value
.

Unfortunately, this predicate is currently unsupported in Realm -- you can follow https://github.com/realm/realm-cocoa/issues/1328 for updates.

Related

NSPredicate: search for an array of values in relation, NOT

I'm a bit lost, and I hope you can help me.
I have two arrays
let stars = ["Paul", "Ringo"]
let visitors = ["bob", "mary"]
Then I have Core Data entities Rockstar and Person. And a one-to-many relation fans between the two.
Now I want to find a couple of specific Rockstars, and make sure that they don't have visitors as fans.
I try to do that with a compound predicate, roughly like this:
let starsPredicate = NSPredicate(format: "id IN %#", stars)
let fansPredicate = NSPredicate(format: "NOT (fans.personid CONTAINS %#)", visitors)
and finally
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [starsPredicate, fansPredicate])
I'm afraid this results in two questions:
What is the correct syntax for the fansPredicate? It works fine with one value, but it crashes on an array
Is this possible with a compound predicate at all? I think if the Person entity is empty, I get zero records from the compoundPredicate.
This can be achieved with a “SUBQUERY”:
let fansPredicate = NSPredicate(format: "SUBQUERY(fans, $f, $f.personid IN %#).#count = 0",
visitors)
The predicate is true for all Rockstar objects which have no related Person object whose personId is in the given list.

CloudKit: fetching records that have a certain element in a list attribute

I was wondering whether it is possible to form an NSPredicate that would do the following in CloudKit:
Suppose that I have some record type A. Suppose that A has some attribute b that is of type [CKReference]. Let c be some element of type CKReference that could be in b.
I wish to query for all records of type A that have c in the list b. Is it possible to do this with NSPredicate?
Thanks in advance!
EDIT
I basically want to do this (CloudKit - NSPredicate for finding all records that contain specified CKReference in a reference list), but in Swift 3. I'm having trouble finding good resources online that explain how to use contains in an NSPredicate.
Here's what ended up working for me, in terms of the variables I used in the question:
letc= CKReference(recordID: userRecordID!, action: .none)
let joinedPredicate = NSPredicate(format: "%K CONTAINS %#",b,c).
let joinedQuery = CKQuery(recordType:A, predicate: joinedPredicate)
var predicates = [NSPredicate]()
predicates.append(NSPredicate(format: "("your key" CONTAINS[cd]%#)", filterString))
and initialising CKrefrence in swift
let reference = CKReference(recordID: example.recordID, action: .deleteSelf)
you can create CKReference object by using-- let reference = CKReference(recordID: example.recordID, action: .deleteSelf) where example.recordId will be record Id from your CloudKit and after creating you need to have your filter using predicate where predicates.append(NSPredicate(format: "("your key" CONTAINS[cd]%#)", filterString)) filter string will contains reference of your created CKReference object –

Realm subquery with List count in Swift

I have
class Car : Object
{
let queries : List<QueryModel> = List<QueryModel>()
}
and
class QueryModel : Object
{
let location : String = ""
}
Now how do I write that NSPredicate to fetch just that cars which have queries with location equal to 'London'?
p.s. It's a known fact that things like #count do not work on Swift List class...
p.p.s. I need it as a predicate because this is the only way RBQFetchedResultsController knows how to do it's job.
How I thought it could've been written was something like NSPredicate(format: "SUBQUERY(queries, $query, $query.location == %#)", 'London'). But nothing like this ever passes Realm's predicate validation :)
You can write
NSPredicate(format: "ANY queries.location = %#", locationString)
If you want to add other filtering, you can create other NSPredicate and then use
NSCompoundPredicate(andPredicateWithSubpredicates: [pred1, pred2])
to combine the filters.
Now, if you want to filter cars, you have to prepare a
let request = FetchRequest<Car>(realm: realm, predicate: predicate)
then you can use RBQFetchedResultsController to execute the request.

Sort fetch request based on relationship attribute

Let's say I have to entities; Item and LocalizableString. The LocalizableString entity have two attributes; string and locale. The Item entity have a to-many relationship to LocalizableString called localizedTitles. Where there's one string entity per "locale".
Now, in my app I have some context/setting that determines what locale I want to use when showing the UI. So let's say I have a UITableViewController with an NSFetchedResultsController handling the data flow.
My question is: can I sort the Item entities based on the LocalizableString's string property where locale is for example en? And can I do this in the fetch request, not after having fetched all items?
Sure you can do that, but you do not have to fetch any particular locale upfront. Your fetched results controller would just fetch the Item objects, and you can then refer to the correct string as you need it.
One way to implement this is to add a convenience function to the Item class, something like the following
func titleWithLocale(identifier: String) -> String? {
if let title = self.localizedTitles.filter
{ $0.locale == identifier }
.first as? LocalizableString {
return title.string
}
return nil
}
Most likely you will have to tweak this code to conform to the strict typing of Swift, but you get the idea.
If you need to sort by the title string, perhaps you need a different approach. If you know that each Item has a localized title in the respective locale you can fetch the LocalizedTitle entity with a predicate the filters for the locale:
request.predicate = NSPredicate(format: "locale = %#", "en")
Obviously, you can sort by string with the usual sort descriptors. Now, to populate your table, you get to the item by following the relationshp in the other direction.
let title = fetchedResultsController.objectAtIndexPath(indexPath)!
let item = title.item
I ended up doing a fetch request for my LocalizableString entity instead. With a predicate that checks the locale and the inverse relationship:
NSPredicate(format: "locale == %# AND itemName != nil", locale)

CloudKit - NSPredicate for finding all records that contains multiple CKReferences in a reference list

I'm working on Joke app that uses CloudKit
Each joke has a reference list to some categories/tags.
I'm trying to query all jokes that has some specific tags. For instance I want to find all jokes that is in the categories of Animal and Doctor.
Right now I have tried with the following code
let tagRecords = tags.map { CKReference(record: $0.record, action: .None) }
let predicate = NSPredicate(format: "tags CONTAINS %#", tagRecords)
let query = CKQuery(recordType: "Jokes", predicate: predicate)
Basically what the above does is first of all creating an array of references and then make a predicate to find the tags the contains those references
Unfortunately this doesn't work
I get the following error
server message = "Internal server error""
So the question is: How do you find all records that contains all references in a reference list?
Assuming that tags is a relationship or an array of strings, you could try with the following predicate:
let predicate = NSPredicate(format: "ANY tags IN %#", tagRecords)
Hope this helps.

Resources