Filter realm objects to only get one (distinct) object by attribute
As of Realm Swift 3.1 you can do let movies = realm.objects(Movie.self).sorted(by: ["id", true]).distinct(by: ["genre"])
, which will select the first Movie
of each genre using the sort order applied before the distinct operation.
How to get unique value from Realm database in swift
Starting from Realm 3.10 it's now possible to
Add Results.distinct(by:) / -[RLMResults
distinctResultsUsingKeyPaths:], which return a Results containing only
objects with unique values at the given key paths.
Old response - before Realm 3.10
It is not possible yet to obtain a "distinct"-like functonality from a Realm query (track the open issue here)
However, there are some workarounds suggested in the thread I mentioned above (please read it to get the full context), by user apocolipse
:
// Query all users
let allUsers = Realm().objects(User)
// Map out the user types
let allTypes = map(allUsers) { $0.type }
// Fun part: start with empty array [], add in element to reduced array if its not already in, else add empty array
let distinctTypes = reduce(allTypes, []) { $0 + (!contains($0, $1) ? [$1] : [] )
Or better yet, a different approach using Set
s (by user jpsim
):
let distinctTypes = Set(Realm().objects(User).valueForKey("type") as! [String])
Obviously the workarounds aren't as efficient as a direct DB query, so use with care (and testing under realistic load).
Return unique/distinct values with Realm query
I found out Realm doesn't fully support distinct queries yet. The good news is I also found a workaround for it, on this github issue.
Objective-c
RLMResults *messages = [Message allObjects];
NSMutableArray *uniqueIDs = [[NSMutableArray alloc] init];
NSMutableArray *uniqueMessages = [[NSMutableArray alloc] init];
for (Message *msg in messages) {
NSString *jabberID = msg.jabberID;
Message *uniqueMSG = (Message *)msg;
if (![uniqueIDs containsObject:jabberID]) {
[uniqueMessages addObject:uniqueMSG];
[uniqueIDs addObject:jabberID];
}
}
Swift 3.0
let realm = try! Realm()
let distinctIDs = Set(realm.objects(Message.self).value(forKey: "jabberID") as! [String])
var distinctMessages = [Message]()
for jabberID in distinctIDs {
if let message = realm.objects(Message.self).filter("jabberID = '\(jabberID)'").first {
distinctMessages.append(message)
}
}
Realm Filter Issue
Let me shorten and repeat the question
The objective is to get the qty of a particular InventoryModel based on the
StockModel quantities stored in the ofStock list. (instead of storing
it in InventoryModel totalUnit property).
Using the InventoryModel and StockModel in the question, if we create an inventory model for widget
let inv = InventoryModel()
inv.name = "Widget"
and then add two StockModel objects to its ofStock List
let sm0 = StockModel()
sm0.quantity = 1
let sm1 = StockModel()
sm1.quantity = 2
inv.ofStock.append(objectsIn: [s0, s1])
If we then want to get the total inventory available for the Widget object, it's a single line
let sum: Int = realm.objects(StockModel.self).filter("ANY parentInventory.name == 'Widget'").sum(ofProperty: "quantity")
print(sum)
and the output is 3
Note that we are transversing back through the StockModels to get the parent they belong to.
EDIT
The OP also wanted to have a query to do the following (from the comments)
I want to query for all InventoryModels that have ANY stock models
that have a quantity > 0
Here's the query that returns all InventoryModel objects where any StockModels in the ofStock property have a quantity property greater than 0
let results = realm.objects(InventoryModel.self).filter("ANY ofStock.quantity > 0")
Realm - how to query for a List greater than 0 objects
I was so close!
let results = realm.objects(Person.self).filter("cats.@count > 0")
(needed the "@" before count
)
How to address key of retrieved object, in Realm, Swift?
You are using a property called name
in your filter
string but in your UserRecords
class the property is called username
. Also you have to create the filter string differently:
var currentlogin = realm.objects(UserRecords).filter("username = '\(LogUsernameTextField.text!)'")
Also be aware that the filter method returns a list of UserRecord
objects that match the filter and not a single object. So calling if currentlogin.password == ...
will cause an error.
The list only has 1 item (because the username is unique) but it is still a list. So to access the UserRecord
object you can call first
:
var currentlogin = realm.objects(UserRecords).filter("name = LogUsernameTextField.text!").first
Also the text
property of UITextField
returns an Optional, so you have to unwrap it.
Related Topics
Swift Encode Tuple Using Nscoding
Split Uint32 into [Uint8] in Swift
How to Build a Swift Package for iOS Over Command Line
Swift (iOS 8 Sdk) Convert Unmanaged<Abmultivalueref> to Abmultivalueref
Swiftui Change View with Button
How to Show a Window Without Stealing Focus on MACos
iOS - Add Image and Text in Title of Navigation Bar
Swipe Animation for Remove Cell in Uicollectionview - Swift 2.0
How to Link to a 3Rd Party Swift Framework
How to Find the Index of an Item in a Multidimensional Array Swiftily
How to Shuffle an Array So That No Two Consecutive Values Are the Same
Nsmanagedobject Changes Do Not Trigger Objectwillchange
How to Make Uitextfield Behave Like a Uisearchbar in Swift
Cross Platform Aes Encryption Between iOS and Kotlin/Java Using Apples Cryptokit
In Swift, How to Write a Generic Function to Resize an Array
Dynamic/Runtime Dispatch in Swift, or "The Strange Way Structs Behave in One Man's Opinion"