Подзапрос Realm для фильтрации данных из 1 таблицы относительно таблицы 2 - PullRequest
0 голосов
/ 24 сентября 2019

Предположим, что у меня есть две модели и соответствующие таблицы в базе данных 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)

Что я хочу: Я хочу сделать следующее.

Я хочу получить весь список клиентов, но я также хочу, чтобы в списке был такой клиент, который чаще покупает товары.Я имею в виду, что я хочу заказать список на основе клиентов, которые покупают больше времени в нашем магазине.Для этого я могу получить его из идентификатора клиента в таблицах счетов.Но я не знаю, как это сделать в Realm.

Я знаю, что это можно сделать с помощью подзапроса, но я не понимаю, как это сделать в Realm.Пожалуйста, скажите мне, что будет запрос / предикат здесь, чтобы получить желаемые результаты.

1 Ответ

1 голос
/ 26 сентября 2019

У меня есть два ответа, но сначала нужно обратиться к нескольким вещам.

Для обоих ваших классов, если вы хотите, чтобы ими управлял Realm, вам нужно включать @objc перед каждой переменной, которую вы хотитеУправляемый

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

или при желании добавить @objcMembers к имени класса

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

Другое дело, что свойства класса (переменные) всегда должны быть в нижнем регистре, имена классов должны начинаться с верхнегокейс.Ничто не должно быть все CAPS.

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

создает уникальные первичные ключи для ваших объектов.Устраняет необходимость в индексировании, уникальности, увеличении и т. Д.

...