Что у меня есть: снимок всех пользователей с кучей операторов if, который в конечном итоге возвращает массив отображаемых пользователей.

Что мне нужно: массив конечных пользователей, который будет использоваться в .query в строке, предшествующей снимку.

Зачем мне это: эта строка предназначена для того, чтобы вся база данных пользователей не запускалась на клиенте.

В частности, что мне нужно запросить: A ) пользователей, у которых есть дочерняя «подпись» (метка времени) с меткой времени, которая находится в «сегодня», И, B ) которые находятся на расстоянии 3000 миль от текущего пользователя.

JSON БД

    "people" : {
"02PdiNpmW3MMyJt3qPuRyTpHLaw2" : {
  "Coordinates" : {
    "latitude" : -25.809620667034363,
    "longitude" : 28.321706241781342
  },
  "PhotoPosts" : "https://firebasestorage.googleapis.com/v0/b/daylike-2f938.appspot.com/o/images%2F02PdiNpmW3MMyJt3qPuRyTpHLaw2%2FPhotoPosts?alt=media&token=24fee778-bcda-44e3-aa26-d7c2f8509740",
  "caption" : 1602596281762, /// this is timestamp
  "postID" : "02PdiNpmW3MMyJt3qPuRyTpHLaw2"
},
  "e1" : “cvvvv666",
  "e2" : "aol.com",
  "      "postID" : "0RnqWV7Gd9Z0bUW9nUvizMQOjK73",
  "users" : "cvvvv666@aol.com"
},
    

.

var dict = CLLocation()
         ...
dict = CLLocation(latitude: lat, longitude: lon)
        ...
let thisUsersUid = Auth.auth().currentUser?.uid
    //this line below is where the refArtists2 query should go. in other words send all users to device that meet the 2 if statements, which is represented by self.people.append(peopl)//
    let refArtists2 = Database.database().reference().child("people").queryOrdered(byChild: "caption").queryEqual(toValue: ANY Timestamp in today).queryOrdered(byChild:Coordinates). queryEqual(toValue:ThoseCoordinates which make the distance to current user less than 3000 miles)     
    refArtists2.observe(DataEventType.value,  with: {  snapshot in
        if snapshot.childrenCount>0{
            self.people.removeAll()
            for people in snapshot.children.allObjects as! [DataSnapshot] {
         if people.key != thisUsersUid {
                let peopleObject = people.value as? [String: AnyObject]
                let peopleCoordinates = peopleObject?["Coordinates"] as? String
                let peoplecaption = peopleObject?["caption"] as? Int //is timestamp
                let peoplepostID = peopleObject?["postID"] as? String
                let coordSnap = people.childSnapshot(forPath: "Coordinates")
                guard let lat = coordSnap.childSnapshot(forPath: "latitude").value as? CLLocationDegrees else { return  }
                guard let lon = coordSnap.childSnapshot(forPath: "longitude").value as? CLLocationDegrees else { return  }
                let locCoord = CLLocation(latitude: lat, longitude: lon)
                let coordSnap12 = people.childSnapshot(forPath: "caption").value as? Int ?? 0
                let date = Date(timeIntervalSince1970: TimeInterval(coordSnap12)/1000.0)
                //let secondsInDay = 86400
                **if Calendar.current.isDateInToday(date)** {
                    let distance = locCoord.distance(from: self.dict)
                    print(distance, "distancexy")
                    **if distance/1609.344 < 3000**{
                        let peopl = Userx(Coordinates: peopleCoordinates, distance:distance, caption: peoplecaption, postID: peoplepostID)
                        self.people.append(peopl)
                        let d = people.key as! String
                        self.printPersonInfo(uid:d)   ///////This is used to reload the data
                    } else {
                        print ("w")
                    }
                } else {
                    print ("alphaaa") 
                }   
            }
            print("aaaaaaaa", self.people.map {$0.distance})    
        } 
        self.people.sort { ($0.distance ?? 0) < ($1.distance ?? 0) }     ////////This sorting with distance is used with returning the cell. people is used as uid array to return the cell.   
    }      
})
} else {
    print("no")
}
})
                            

Дополнительное предупреждение: сортировка self.people.sort { ($0.distance ?? 0) < ($1.distance ?? 0) } важна, поэтому запросы не должны этому препятствовать. Меня немного беспокоит использование queryOrdered, поскольку он упорядочивает массив пользователей в неправильном порядке. Если это так, запрос C ) должен иметь следующий вид: пользователи должны быть в порядке следования ближайших к пользователю, вошедшему в систему. Самый дальний от вошедшего в систему пользователь должен идти последним в массиве.

Другой способ спросить это: вместо того, чтобы запускать моментальный снимок всех пользователей, как вы запрашиваете "сортировку конечных результатов" моментального снимка при создании моментального снимка?

Отметка времени в секундах с 1970 года.

Моя попытка запроса даты ниже. Я взял код и попытался поместить код, который получает дату перед фактическим запросом (в настоящее время код, который получает дату , находится после моментального снимка всех пользователей).

    var ppp: String!  ////this should be the uid of all users in db

    let people = Database.database().reference().child("people").child(self.ppp).child("captions")
people.observe(DataEventType.value, with: {  snapshot in
    let captionss = snapshot.value as? Int ?? 0
    let date = Date(timeIntervalSince1970: TimeInterval(captionss)/1000.0)       
    let query1 = Database.database().reference().child("people").queryOrdered(byChild: "caption").where?(isDateInToday(date))
0
uuuuuu 1 Ноя 2020 в 19:02

1 ответ

Лучший ответ

Изменить: этот ответ находится в Firestore, а не в базе данных в реальном времени. Однако концепции те же.

Вопрос - несколько вопросов в одном; спрашивать о расстоянии, составных запросах и о том, как запрашивать Firebase в целом. Я отправлю этот ответ, чтобы ответить на два вторых вопроса, а удаленные запросы рассматриваются в комментарии к вопросу.

Как только шаблон запроса будет понят, они станут проще и, что наиболее важно; становится более очевидным, что то, как структурированы ваши данные, зависит от того, какие запросы вы хотите выполнить с этими данными.

Предположим, у нас есть коллекция пользователей с пользовательскими документами - каждый documentId - это user uid.

users
   uid_0
      name: "Leroy"

А затем у нас есть сообщения для пользователей - каждое сообщение содержит некоторый текст, временную метку сообщения, uid пользователя, который его опубликовал, какова тема и URL-адрес изображения, которое появляется в сообщении. Обратите внимание, что я храню сообщения в отдельной коллекции; зачем читать кучу пользовательских данных, когда мы хотим знать только об их посте.

posts
   post_id
      postText: "pretty flowers"
      postDate: "20201103"
      postUrl: "www....."
      postUid: "uid_0"
      postTopic: "flowers"

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

Для этого нам понадобится составной запрос, а затем подзапрос для получения имени плаката.

func getTodaysPostsAboutFlowers() {
    let postsCollection = self.db.collection("posts")
    let query = postsCollection.whereField("postDate", isEqualTo: "20201103").whereField("postTopic", isEqualTo: "flowers")
    query.getDocuments(completion: { snapshot, error in
        if let err = error {
             print(err.localizedDescription)
             return
         }

         guard let docs = snapshot?.documents else { return }

         for doc in docs {
            let postText = doc.get("postText") as? String ?? "No text"
            guard let postersUid = doc.get("postUid") as? String else { return }
            self.outputPostTextAndUserName(withText: postText, andUid: postersUid)
         }
    })
}

Вышеупомянутое выполняет составной запрос как для поля postDate, так и для поля postTopic.

Вышеупомянутое затем вызывает другую функцию для получения имени пользователя и вывода как имени, так и того, что они сказали.

func outputPostTextAndUserName(withText: String, andUid: String) {
    let usersCollection = self.db.collection("users")
    let theUserDoc = usersCollection.document(andUid)
    theUserDoc.getDocument(completion: { documentSnapshot, error in
        if let err = error {
             print(err.localizedDescription)
             return
         }

        if let doc = documentSnapshot {
            let postersName = doc.get("name") as? String ?? "No Name"
            print("\(postersName) posted: \(withText)")
        }
    })
}

И выход

Leroy posted: pretty flowers

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

Изменить . OP спрашивает о запросе узлов, содержащих сегодня. Простое решение состоит в том, чтобы иметь один дочерний узел, содержащий метку времени, которая будет содержать конкретные данные даты, а затем другой дочерний узел, содержащий только данные сегодня в формате ГГГГММДД.

People uid_x timetamps: 9023490823498 // Дата (timeIntervalSince1970: todaystamp: "20201106" // формат ггггммдд

Это делает очень простым запрос узлов, которые содержат сегодня.

0
Jay 6 Ноя 2020 в 17:40