Realm Subquery to filter data from 1 table w.r.t table 2

守給你的承諾、 提交于 2019-12-01 13:56:55

I have two answers but there are a couple of things to address first.

For both of your classes, if you want them to be managed by Realm you need to include @objc before each var you want managed

public class Customer :Object {
   @objc dynamic var  Id : String = ""

or optionally add @objcMembers to the class name

@objcMembers class Customer :Object {
       dynamic var  Id : String = ""

The other thing is that class properties (vars) should always be lower case, class names should start with upper case. Nothing should be all CAPS.

public class Customer :Object {
   @objc dynamic var  customer_id : String = ""
   @objc dynamic var  name : String = ""

First solution is using your current structure:

var topCustomers = [(String, Int)]() //stores the customer id and count in an array of tuples
let results = realm.objects(Bills.self) //get all the bills
let allCustomerIds = results.map{ $0.CustomerId } //get a list of all of the customer id's
let uniqueIds = Set(allCustomerIds) //create a set of unique customer ids

for custId in uniqueIds { //iterate over the array of unique customer id's
    let count = results.filter("CustomerId == %@", custId).count // get a count of each customer id from results
    topCustomers.append( (custId, count) ) //add the customer id and it's count to the array
}

topCustomers.sort { $0.1 > $1.1 } //sort the array by count
for x in topCustomers { //print out the array - the customer with the most bills will be at the top
    print(x.0, x.1)
}

a second, more elegant approach uses a relationship between customers and their bills. This will provide a LOT more flexibility for generating reports, queries and overall organization.

Here's the updated classes:

class CustomerClass: Object {
   @objc dynamic var  customer_id = UUID().uuidString
   @objc dynamic var  name = ""
   @objc dynamic var  address = ""

   let billList = List<BillClass>()

   override public class func primaryKey() -> String? {
      return "customer_id"
   }
}

class BillClass: Object {
    @objc dynamic var  bill_id = UUID().uuidString
    @objc dynamic var  amount = ""

    override public class func primaryKey() -> String? {
        return "bill_id"
    }
}

and then some very short code to accomplish the same thing as in the first example

let customers = realm.objects(CustomerClass.self) //get all customers
let results = customers.map { ($0.name, $0.billList.count) } //iterate over all, creating tuple with customer name & bill count
let sortedResults = results.sorted(by: { $0.1 > $1.1} ) //sort by bill count, descending
sortedResults.forEach { print($0) } //print the results, customer will most bills at top

Notes the use of UUID().uuidString

@objc dynamic var  bill_id = UUID().uuidString

creates unique primary keys for your objects. Eliminates dealing with indexing, uniqueness, incrementing etc.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!