Realm子查询从1个表和2个表中筛选数据 [英] Realm Subquery to filter data from 1 table w.r.t table 2
问题描述
假设我在Realm数据库中有两个模型和对应的表
Suppose that I have two models and corresponding tables in the Realm Database
public class Customer :Object {
dynamic var Id : String = ""
dynamic var NAME : String = ""
dynamic var Address : String = ""
override public class func primaryKey() -> String? {
return "Id"
}
}
public class Bills :Object {
dynamic var Id : String = ""
dynamic var Amount : String = ""
dynamic var CustomerId : String = ""
override public class func primaryKey() -> String? {
return "Id"
}
}
我在做什么:通过这样做,我很容易获得所有客户的列表 这个
What I am doing: I am getting list of All customers easily by doing this
realmObj.objects(Customer.self)
我想要的内容:我要执行以下操作.
What I want: I want to do followings.
我想获得所有客户"列表,但我也希望列表中包含最常购买商品的此类客户.我的意思是,我希望根据从我们的商店购买更多时间的客户来订购商品.为此,我可以从帐单"表中的客户ID中获取它. 但是我不知道如何在Realm中进行操作.
I want to get all the list of Customers but I also want that the list contain such customer on top who purchases items more often. I mean I want the list ordering on the basis of customers that purchases more time from our shop. For this I can get it from the customer Id in Bills tables. But I do not know how to do it in Realm.
我知道可以通过子查询来完成,但是我没有在Realm中进行操作.请在此处告诉我什么是查询/谓词,以获取所需的结果.
I know it can be done through subquery but I am not getting how to do it in Realm. Please tell me what will be query/Predicate here to get the desired results.
推荐答案
我有两个答案,但首先要解决几件事.
I have two answers but there are a couple of things to address first.
对于这两个类,如果希望它们由Realm管理,则需要在每个要管理的变量之前添加@objc
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 = ""
或选择将@objcMembers添加到类名
or optionally add @objcMembers to the class name
@objcMembers class Customer :Object {
dynamic var Id : String = ""
另一件事是,类属性(变量)应始终为小写,类名称应以大写开头.什么都不是全部CAPS.
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.
这是更新的课程:
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
注意使用UUID().uuidString
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.
这篇关于Realm子查询从1个表和2个表中筛选数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!