Как запрашивать и считать записи в базе данных области - PullRequest
0 голосов
/ 21 апреля 2020

Мне нравится строить поиск, по которому пользователь может шаг за шагом фильтровать результаты. Так что без выбора, есть кнопка, которая говорит, например, «1 234 567 результатов», и если вы выбираете цвет, например, набор результатов сжимается ... мы все знаем этот вид поиска. Я делал это много раз, но это впервые в Realm (и swift).

Допустим, у меня есть 5 человек в моей Персональной таблице, тогда на человека приходится около 145 224 записей о собаках и около 2 507 327 кошек записи на собаку. Как запросить и посчитать вложенные объекты в области?

    class Person: Object {
        @objc dynamic var name = ""
        let dogs = List<Dog>()
        // ...other Properties
    }

    extension Person {
        static func all(in realm: Realm = try! Realm()) -> Results<Person> {
            return realm.objects(Person.self)
        }
    }

    // counts -> 145,224 db entries per person
    class Dog: Object {
        @objc dynamic var name = ""
        dynamic var Person: Person?
        let cats = List<Cats>()
        // ...other Properties as well
    }

    extension Dog {
        static func all(in realm: Realm = try! Realm()) -> Results<Dog> {
            return realm.objects(Dog.self)
        }
    }

    // counts -> 2,507,327 db entries per dogs
    class Cat: Object {
        @objc dynamic var name = ""
        dynamic var Cat: Cat?
    }

    extension Cat {
        static func all(in realm: Realm = try! Realm()) -> Results<Cat> {
            return realm.objects(Cat.self)
        }
    }


    // Get the default Realm
    let realm = try! Realm()

    // Query Realm for all dogs
    let dogs = Person.all(in: realm).flatMap { $0.dogs }
    dogs.count // => takes ~20 seconds to count

Другими словами, каков самый быстрый способ получить (подсчитать) все записи Dog всех людей (пока пусть кошки будут рядом).

Я попытался обойти проблему, ограничив результаты до 1000. Если результаты> 1000, пометьте кнопку примерно так: «> 1000 результатов». Но даже если это займет очень много времени (я думаю, все равно все посчитают).

Так что же я не так сделал? Любые предложения приветствуются. Спасибо, всего наилучшего

1 Ответ

0 голосов
/ 21 апреля 2020

То, как вы подсчитывали, требует, чтобы все Dog объекты были загружены в память, что действительно неэффективно. Вот почему вы видели такие плохие показатели. Вы хотите воспользоваться функциями отложенной загрузки Realm. Вы можете прочитать об этом.

Я бы обновил ваш Dog объект, избавившись от управляемого свойства Person и заменив его LinkingObjects. Если вы сохраните Dog в Person.dogs Списке, то область создаст для вас обратную ссылку на Person. Скорее всего, вы захотите сделать то же самое с Cat. Таким образом, вы можете настроить несколько действительно мощных вложенных запросов.

Для удобства вы можете добавить вычисляемое свойство Person для индексации в LinkingObjects. Просто знайте, что вы не сможете использовать это свойство ни в одном из ваших запросов.

class Dog: Object {
    @objc dynamic var name = ""
    let persons = LinkingObjects(fromType: Person.self, property: "dogs")
    var person: Person? { persons.first }
}

Один из способов подсчета количества - это запрос всех объектов Person и суммирование числа * 1018. * для каждого Person.

let count = realm.objects(Person.self).reduce(0) { result, person in
    return result + person.dogs.count
}

Другим вариантом является запрос Dog объектов, имеющих соответствующий Person. Если Dog нет в списке Person.dogs, запрос не будет отображаться.

let realm = try! Realm()
let count = realm.objects(Dog.self).filter("persons.@count > 0").count

Любой из этих вариантов будет намного, намного эффективнее, чем у вас.

Надеюсь, это поможет.

...