В моей структуре базы данных userDatabase/userID/Customers у меня есть два клиента. Например путь:
usersDatabase
g8voYf1yoChnpmhkoPgtmO4FQT62 - (uid)
Customers
Tom Smith (customer with custom ID)
-LDFZw1tca8KOrnqyyWH - (auto id of customer child)
Status of Service: "Open service"
Ben Thomas (customer with custom ID)
-LDFZw1tca8KOjgoenBN - (auto id of customer child)
Status of Service: "Open service"
Можно ли получить количество значений «Открытая услуга» от всех клиентов в моей базе данных? Теперь я знаю только, как распечатать это значение для каждого клиента ...
Мой код для получения значения из базы данных:
let userID = Auth.auth().currentUser?.uid
let usersDatabaseRef = Database.database().reference().child("usersDatabase").child(userID!).child("Customers")
usersDatabaseRef.observe(.value, with: { snapshot in
var totalCustomerCount = 0
for child in snapshot.children {
let childSnap = child as! DataSnapshot
let childrenRef = childSnap
totalCustomerCount += Int(childrenRef.childrenCount)
print("user \(childSnap.key) has \(childrenRef.childrenCount) customers")
let userCustomerSnap = childSnap
for customer in userCustomerSnap.children.allObjects as! [DataSnapshot] {
let customerSnap = customer
let dict = customerSnap.value as! [String: Any]
let stat = dict["Status of Service"] as! String
let myStatistic = PrintModel(status: stat)
self.statistic.append(myStatistic)
print("Statistic: \(String(describing: myStatistic.status))")
}
}
print("... and there are \(totalCustomerCount) total customers")
})
Например, мой журнал теперь показывает:
но хочу показать:
Не могли бы вы показать мне свой ответ на примере кода?
@ KrzysztofŁowiec Есть ли возможность изменить структуру базы данных? Что касается текущей структуры базы данных, вам нужно будет получать всех клиентов, как вы это делаете.
@TheTiger В этой структуре нет ничего плохого, пока возвращаемые совпадения не превышают емкость устройства. Если это будет проблемой, можно использовать отдельный узел считать, если OP интересуется просто счетчиком, а не самими данными. например когда дочерний элемент добавлен или удален из узла клиентов, увеличьте / уменьшите отдельный узел счета на 1.
@ KrzysztofŁowiec tom_smith является клиентом ИЛИ tom_smith может иметь несколько клиентов? Не могли бы вы расширить свой пример базы данных несколькими ключами и значениями. Тогда я попробую.





При структурировании данных Firebase структура обычно основана на том, что вы хотите получить от нее. В этом случае требуемые данные находятся слишком глубоко в опубликованной структуре, чтобы быть полезными. Итак, изменение структуры сделает это несложно.
Разделите данные на их собственные узлы, денормализуя данные. Как это
users
uid_0
//some info about this user
open_service_calls
auto_id_0: true
auto_id_1: true
uid_1
//info about this user
customers
customer_id_0
customer_name: "Tom Smith"
open_service_calls
auto_id_0: true
customer_id_1
customer_name: "Ben Thomas"
open_service_calls
auto_id_1: true
service_calls
auto_id_0
customer_id: customer_id_0
user_id: "uid_0"
status_of_service: "Open service"
auto_id_1
customer_id: customer_id_1
user_id: "uid_0"
status_of_service: "Open service"
Это позволяет запрашивать клиентов, пользователей и решать этот вопрос, легко подсчитывая все открытые службы в базе данных для всех пользователей и клиентов; запросить service_calls / status_of_service для "Открытой службы"
Это также позволяет вам быстро получить доступ ко всем обращениям в службу поддержки, открытым или закрытым для любого пользователя, любого клиента и даже просто открытым вызовам службы для клиента пользователя.
Дополнительные узлы будут предлагать дополнительную гибкость запросов - хранение идентификатора пользователя в узле клиента позволит сверхлегкому запросу получить всех клиентов для конкретного пользователя, даже если у них нет запросов на обслуживание; все зависит от того, что вы хотите получить от Firebase.
--- Старый ответ ниже ---
Согласно моему комментарию к исходному вопросу, этот ответ включает использование глубокого запроса для запроса дочерний элемент дочернего узла клиентов. Идея здесь в том, что внутри пользовательского узла есть узел Customers, где каждый дочерний ключ - это имя клиента, а значение этого узла - пара ключ: значение строки «serviceID», а затем значение, которое может содержать другие дочерние узлы. о сервисе.
Важной частью глубокого запроса является сохранение последовательно именованных дочерних ключей, которые вы запрашиваете - в этом случае мы используем ключ serviceID, чтобы запрос мог правильно разрешить путь, а затем любой из дочерних узлов этого может быть запрашивается: status_of_service, возможно, отметка времени или даже местоположение службы
Первоначальная структура до ее изменения была
Customers
Tom Cruise
serviceID
status_of_service: "Open service"
//timestamp of service?
//location of service?
//other data about service we may need to query?
Ben Smith
serviceID:
status_of_service: "Open service"
Обратите внимание, что для этого ответа self.ref = my firebase, поэтому клиенты являются прямым потомком этого пути.
let ref = self.ref.child("Customers")
let query = ref.queryOrdered(byChild: "serviceID/status_of_service")
.queryEqual(toValue: "Open service")
query.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
print(snap)
}
})
выход - два клиентских узла
tom_smith
serviceID
status_of_service: "Open service"
another_customer
serviceID
status_of_service: "Open service"
Думаю, serviceID имеет какое-то значение, а не текст serviceID.
Но можно ли получить количество status_of_service, равное «Open service» (в данном случае 2)?
@TheTiger serviceID - это ключ, а значение этого ключа - другая пара ключ: значение status_of_service: "Открыть услугу". serviceID должен быть этой строкой в каждом узле, чтобы глубокий запрос работал. Другими словами, у него есть строка serviceID, поэтому Firebase знает путь для запроса Открытая служба - если бы этот текст был другим, это был бы другой путь, возможно, в каждом узле, и вы не могли бы выполнить глубокий запрос.
@ KrzysztofŁowiec Конечно, просто распечатайте (snapshot.childrenCount). Это напечатает, сколько узлов было извлечено, которые соответствуют запросу Открытая служба
Этот код не работает с моей базой данных. Что, если полный путь к базе данных - не Customers/Tom Smith/serviceID/Status of service: Open service, а usersDatabase/g8voYf1yoChnpmhkoPgtmO4FQT62/Customers/Tom Smith/-LDFZw1tca8KOrnqyyWH/Status of service: Open service?
@ KrzysztofŁowiec Как видите, важно включить структуры Firebase в ваш первоначальный вопрос - иначе мы будем гадать. Можете ли вы удалить структуру в своем вопросе и заменить ее фрагментом вашей реальной структуры (пожалуйста, в виде текста, без изображений). Я предполагаю, что вы не сможете делать то, что вам нужно, с вашей текущей структурой, но давайте взглянем.
@Jay Что вы скажете теперь об обновленной структуре БД? Я был прав насчет serviceID, он имеет какое-то значение, а не текст serviceID. Я также был прав относительно структуры db в моем вчерашнем комментарии, и теперь вы придумали изменить структуру db.
@TheTiger Я не понимаю, почему вы разместили этот комментарий или считаете, что были «правы» в чем-то. В решении мой мы использовали Глубокий запрос для доступа к данным, хранящимся в узле. Чтобы это работало, имена путей должны быть согласованными - вот почему в моем первоначальном ответе мы использовали путь serviceID / status_of_service, где serviceID фактически является ключом, а это означает, что это будет буквальная строка serviceID. Вам следует взглянуть на документацию, которую я связал, так как это мощный инструмент для доступа к дочерним данным.
@Тигр. Взгляните на раздел старого ответа, который я оставил в ответе. Первоначальное намерение состояло в том, чтобы сохранить узел с ключом serviceID согласованным для всех клиентов - поэтому глубокий запрос мог быть выполнен на любом из его дочерних узлов; статус службы, возможно, местоположение или диапазон отметок времени. Дело в том, что если вы хотите выполнить глубокий запрос, имя родительского ключа не может быть другим. Мы выбираем слово serviceID для этого примера, но с тем же успехом это может быть Сервисы или service_data или действительно любая строка - при условии, что она согласована. Если у вас есть альтернативный ответ, опубликуйте его!
@Jay, но что, если я помещаю значение Статус службы каждого клиента в tableview (например: мои 4 ячейки в tableview показывают "Открытая служба", "Во время обслуживания", "Открытая служба", "Открытая служба"), а затем получаю количество ячеек содержание (пример: 3 («Открытая услуга) и 1 (« Во время обслуживания) ») - возможно ли это?
@ KrzysztofŁowiec Я не думаю, что понимаю вопрос - вы не должны использовать элементы пользовательского интерфейса для получения подсчетов - которые должны быть получены из источника данных, поддерживающего tableView. Используя структуру, которую я предложил в своем ответе, должно быть довольно легко получить подсчеты любого вида услуг, открытых, находящихся в процессе, закрытых и т. д. Либо непосредственно из Firebase, либо из источника данных.
Я отредактировал ваш вопрос и обновил структуру Firebase, так что посмотрите. Чтобы ответить на вопрос, конечно. Просто установите ссылку на your_firebase / customers и выполните Глубокий запрос, где serviceID / status_of_service равно Open service. Я бы посоветовал НЕ использовать имена клиентов в качестве имен узлов - лучше использовать их uid или, возможно, номер клиента. См. Также это