【问题标题】:Realm Subquery to filter data from 1 table w.r.t table 2领域子查询过滤来自 1 个表 w.r.t 表 2 的数据
【发布时间】:2019-09-24 06:39:28
【问题描述】:

假设我在 Realm 数据库中有两个模型和对应的表

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"
    }
}

我在做什么:我正在通过以下方式轻松获取所有客户的列表 这个

realmObj.objects(Customer.self)

我想要什么:我想做以下事情。

我想获取所有客户列表,但我也希望该列表包含最常购买商品的此类客户。我的意思是我希望根据从我们商店购买更多时间的客户来进行列表排序。为此,我可以从 Bills 表中的客户 ID 中获取它。 但我不知道如何在 Realm 中做到这一点。

我知道可以通过子查询来完成,但我不知道如何在 Realm 中完成。请告诉我这里将使用什么查询/谓词以获得所需的结果。

【问题讨论】:

  • 事实上,这两个对象之间没有正式的关系。我看到您将 CustomerId 存储在帐单上,但这只是一个字符串,而不是关系。您应该查看文档中的Relationships。其次,您的目标很模糊 - 购买更多时间的客户。这是什么意思 - 在指定时间内的实际购买次数?或者随着时间的推移购买的物品数量?为此,您需要存储时间戳,例如,您可以查询过去六个月内拥有超过 5 张账单的所有客户。
  • 最初的想法是 Bills 表将保存从商店购买任何产品的客户的 ID。因此我们可以查询 Bills 表中客户重复 ID 的最多数量,以了解特定客户让我们称之为客户 34 购买更多东西让我们说他的 ID 驻留在该表中 44 次。客户 2 购买次数第​​二多,因此他的 id 在 Bills 表中出现 40 次
  • 我已经阅读了这些关系,但不知道你将如何帮助我
  • 我认为在您的 Customer 类中保存一个名为 totalBillsCount 的变量会让您的生活更轻松
  • 我没有得到你

标签: ios swift xcode realm realm-mobile-platform


【解决方案1】:

我有两个答案,但有几件事要先解决。

对于您的两个类,如果您希望它们由 Realm 管理,您需要在要管理的每个 var 之前包含 @objc

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

或可选地将@objcMembers 添加到类名

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

另一件事是类属性(vars)应该总是小写,类名应该以大写开头。任何东西都不应该全部大写。

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

第一个解决方案是使用您当前的结构:

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)
}

第二种更优雅的方法使用客户与其账单之间的关系。这将为生成报告、查询和整体组织提供更大的灵活性。

这是更新后的课程:

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"
    }
}

然后是一些非常短的代码来完成与第一个示例相同的事情

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 的使用

@objc dynamic var  bill_id = UUID().uuidString

为您的对象创建唯一的主键。无需处理索引、唯一性、递增等。

【讨论】:

  • 我以某种方式完成了与您在解决方案 1 中使用的技术相同的任务。其次,您还没有在解决方案 2 中使用子查询。为什么?领域不允许 SUBQUERY ?
  • @A.s.ALI 是的,Realm 允许子查询,但它非常有限(IMO),我们还需要排序,这不能直接用于这个用例。第二种方法是非常简单和简短的代码,因此在这种情况下似乎不需要它。
  • 谢谢杰,但你能帮我解决这个问题吗? softwareengineering.stackexchange.com/questions/398995/…
  • @A.s.ALI 我将在这里回复。这个问题,虽然我明白你在问什么,但非常含糊,并且开始遭到反对。您应该澄清问题并提供更好的用例。即,如果您使用的是 Firebase,则在重新建立连接时,使用 A 所做的更改将自动同步到服务器。如果您使用的是 Realm,它也会以类似的方式运行。如果您使用的是 MySQL,那么如果没有额外的资源,它就不会发生。 MongoDB 也可以同步。看?很多不同的答案,所以问题需要更具体。
  • 在 iOS 中我使用领域,在 android 中我使用 green dao。在服务器端我使用的是 MySql db。所以我希望我的 web、android 和 ios 设备在用户登录 3 个不同的设备(如 web、ios mobile 和 android)时保持同步
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多