Выполнение запроса к базе данных mongo с помощью ParseSwift

#swift #mongodb-query #parse-server

Вопрос:

У меня есть две коллекции в базе данных Mongo.

Вот как выглядит документ в первой коллекции ( MainCollection ):

 _id
:"mzWqPEDYRU"
TITLE
:"ZAZ: I want."
ownerID
:"lGutCBY52g"
accessKey
:"0kAd4TOmoK0"
_created_at
:2020-03-13T11:42:11.169 00:00
_updated_at
:2020-03-13T17:08:15.090 00:00
downloadCount
:2
 

А вот как это выглядит во второй коллекции ( SecondCollection ):

 _id
:"07BOGA8bHG"
_p_unit
:"MainCollection$mzWqPEDYRU"
SENTENCE
:"I love nature peace and freedom."
Order
:5
ownerID
:"lGutCBY52g"
AUDIO
:"07067b5589d1edd1d907e96c1daf6da1_VOICE.bin"
_created_at
:2020-03-13T11:42:17.483 00:00
_updated_at
:2020-03-13T11:42:19.336 00:00
 

Между первой и второй коллекцией существует родительско-дочерняя связь. В последнем документе мы видим поле _p_unit, где часть «mzWqPEDYRU» указывает на идентификатор родителя в первой коллекции.

Хотя я, наконец, получаю то, что хочу, получая элементы второй коллекции с данным родителем, это делается не так, как должно.

У меня есть одна проблема с выборочным запросом SecondCollection . Вот текущий рабочий код:

 func theFunction(element: MainCollection) {
    do {SecondCollection.query().find() {
            result in
            switch result {
            case .success(let items):
                print("items.count = (items.count)")
                var finalCount = 0
                for item in items {
                    // Ignore useless elements:
                    if item.unit?.objectId != element.objectId! {continue}

                    finalCount  = 1
                    /// .... Work with selected element.
                }
                print("finalCount = (finalCount)")
            case .failure(let error):
                print("Error in (#function): (error)")
            }
        }
    }
}
 

То, как написан приведенный выше код, работает в том смысле, что я получаю элементы во второй коллекции, которые меня интересуют. Но этот трюк внутри цикла for для устранения ненужного элемента-не лучший способ.

 if item.unit?.objectId != element.objectId! {continue}
 

Фильтрация должна выполняться в запросе со строкой:

 SecondCollection.query().find()
 

Проблема в том, что все, что я пробовал, провалилось. Я делал такие вещи, как:

 SecondCollection.query("unit" == element.objectId!).find()
 

с миллионом вариаций, но все безрезультатно.

Кто-нибудь знает правильный синтаксис?

В случае, если это может быть полезно, вот как объявляется SecondCollection:

 struct SecondCollection: ParseObject,Identifiable,Equatable,Hashable {
    // These fields are required for any Object.
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?
    
    // Local properties.
    var id:UUID {return UUID()}
    var SENTENCE: String?,
        Order: Int?,
        ownerID: String?,
        AUDIO: ParseFile?,
        unit: Pointer<MainCollection>?
    .......
}
 

Ответ №1:

Во-первых, я не думаю, что приведение всех элементов, а затем «устранение» тех, которые вам не нужны, является хорошим подходом. Таким образом, вы получаете гораздо больше данных, чем необходимо, и это очень неэффективно. Я опробовал ваш код, но вы не прояснили (по крайней мере, для меня), используете ли вы указатели или отношения между этими классами. Подход будет разным для каждого из них. Какой из них вы используете?

ОБНОВЛЕНИЕ: Привет всем! Я думаю, что мог бы сделать так, чтобы это работало так, как тебе нужно. Я создал два класса ParentClass (имя: строка, возраст: число, дети: отношение к детскому классу):

 struct ParentClass: ParseObject {
    //: These are required for any Object.
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    //: Your own properties.
    var name: String?
    var age: Int = 0
    var children: ParseRelation<Self> {
        ParseRelation(parent: self, key: "children", className: "ChildClass")
    }
}
 

И дочерний класс (имя: строка, возраст:число):

 struct ChildClass: ParseObject {
    //: These are required for any Object.
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    //: Your own properties.
    var name: String?
    var age: Int = 0
}
 

Затем я сделал простой запрос, чтобы найти первого Родителя. Вы могли бы использовать метод find() и принести все, что вам нужно, но я сделал это таким образом, чтобы было проще объяснить:

пусть parentQuery = родительский класс.запрос()

     parentQuery.first { result in
        switch result {
        case .success(let found):
            print ("FOUND A PARENT!")
            print(found.name!)
            print(found.age)
            print(found.children)
        case .failure(let error):
            print(error)
        }
    }
 

Теперь, когда у меня есть Родитель (у которого в моем случае два потомка), я использовал метод query() для создания запроса к дочернему классу, содержащему все объекты дочернего класса с найденным родителем:

 do {
                    let childrenObject = ChildClass()
                    try found.children.query(childrenObject).find()
                    { result in
                        switch result {
                        case .success(let allChildrenFromParent):
                            print("The following Children are part of the (found.name!):")
                            for child in allChildrenFromParent {
                                print("(child.name!) is a child of (found.name!)")
                            }
                        case .failure(let error):
                            print("Error finding Children: (error)")
                        }
                    }

                } catch {
                    print("Error: (error)")
                }
 

И весь код закончился так:

 let parentQuery = ParentClass.query()
        
        parentQuery.first { result in
            switch result {
            case .success(let found):
                print ("FOUND A PARENT!")
                print(found.name!)
                print(found.age)
                print(found.children)
                do {
                    let childrenObject = ChildClass()
                    try found.children.query(childrenObject).find()
                    { result in
                        switch result {
                        case .success(let allChildrenFromParent):
                            print("The following Children are part of the (found.name!):")
                            for child in allChildrenFromParent {
                                print("(child.name!) is a child of (found.name!)")
                            }
                        case .failure(let error):
                            print("Error finding Children: (error)")
                        }
                    }

                } catch {
                    print("Error: (error)")
                }
            case .failure(let error):
                print(error)
            }
        }
 

Комментарии:

1. «Я так не думаю … это хороший подход. ….»: Я не могу не согласиться. Вы совершенно правы! Что касается вашего вопроса, я не уверен, что понимаю, какую информацию я должен предоставить, Указатели (для меня) — это всего лишь один из способов выражения отношений. Так не могли бы вы дать мне знать, что вам нужно? Или иным образом дайте мне решения для обоих вариантов, которые вы имеете в виду, и тогда я смогу попытаться выяснить, что для меня важно.

2. @Alex_kusmenkovskiy. Я добавил некоторую информацию в конце поста, я полагаю, что это даст вам информацию, которую вы упустили.

3. @Alex_kusmenkovskiy. Я не совсем понимаю ваше решение. Зная, что в отношениях между родителями и детьми у одного родителя может быть много детей, но у ребенка только один родитель. Я не понимаю смысла «простого запроса для поиска первого родителя». Далее, в моем случае использования вы можете видеть в сообщении, что родительское отношение представлено переменной (указателем), называемой «единица измерения». И в функции я просто получаю все элементы во второй коллекции, имеющие одну и ту же единицу. У меня такое чувство, что ваше решение гораздо более мощное (и сложное), чем то, что мне на самом деле нужно.

4. @Alex_kusmenkovskiy. Я вижу, что вы добавляете это в родительский класс: var children: Синтаксический анализ<Self> { Синтаксический анализ(родитель: я, ключ: «дети», имя класса: «Дочерний класс») } В конце концов, почему бы и нет? Но действительно ли это необходимо? Того, что я делал (проверял значение родителя в запросе), должно быть недостаточно? Мне кажется, что это должно быть проще.