В качестве примера представьте приложение для электронной коммерции, в которое пользователь может загружать столько же элементов, что и у этих элементов есть категории и подкатегории.
Как установить user_id в качестве внешнего ключа в каждом опубликованном элементе, а также item_id в коллекции пользователей, чтобы запрашивать все элементы, отправленные определенным пользователем.
Как мы можем использовать ссылочный тип данных в Firestore для установки внешних ключей?
Есть ли другие способы установки внешних ключей?
Структура базы данных:
Users/doc_id/name..
Categories/fashion/clothing/auto_doc_id/type:denims




Допустим, у вас есть товар в магазине / {shop_id} в виде документа, в котором есть поле ссылки, указывающее на пользователя / {user_id}. Чтобы установить эту ссылку программно:
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
DocumentReference userRef = firestore.collection("user").document({user_id});
Map<String, Object> map = new HashMap<>();
map.put("user", userRef);
firestore.collection("shop").document({shop_id}).update(map);
Чтобы получить этого пользователя, вы можете:
firestore.collection("shop").document({shop_id}).addSnapshotListener(this, (shopItemSnapshot, e) -> {
// Get the shopItem here
// ShopItem shopItem = shopItemSnapshot.toObject(ShopItem.class);
((DocumentReference) shopItemSnapshot.get("user")).addSnapshotListener((userSnapshot, e1) ->
// Get the user from the shopItem document
User user = userSnapshot.toObject(User.class);
});
});
Если вы хотите иметь ссылку на другую таблицу с внешним ключом, вы должны сохранить, например, идентификатор пользователя с данными, с которыми вы хотите работать, например, допустим, у вас есть эта структура
Это из моего проекта, у меня есть, например, узел, который нравится, каждый лайк - это кнопка нажатия, и внутри этой кнопки у меня есть идентификатор пользователя каждого пользователя, которому понравился пост, сообщение представлено с помощью pushKey
Теперь у меня есть еще один узел, который называется users, и внутри вы можете увидеть мой идентификатор пользователя.
Как видите, у меня есть тот же идентификатор пользователя в моем узле users, что и в моем узле Like.
Так что я бы сделал это
Вот как я использую внешний ключ, такой как идентификатор пользователя, для работы с двумя разными узлами.
Теперь предположим, что я хочу собрать все лайки с одной фотографии, я просто просматриваю свой узел лайков, и каждая клавиша нажатия является фотографией, поэтому я делаю тот же процесс и получаю все фотографии и лайки каждой из них. Итак, если я получаю все подобные фотографии, я также получаю идентификатор пользователя, которому понравился, потому что он находится внутри моего узла лайков, а затем с его помощью я могу просто связаться с узлом пользователей и получить все данные от понравившегося пользователя.
PS: нет специальных методов или чего-то еще для создания внешних ключей, это зависит от вашей структуры и того, как вы будете создавать свое приложение. Вы сами устанавливаете свой fk, думая о том, как объединить две таблицы и использовать информацию из обеих, в данном случае двух узлов, которые взаимодействуют друг с другом.
Привет, Гастон. Отличное объяснение того, как это сделать в базе данных Firebase Realtime. Но OP спрашивает о Cloud Firestore (более новая база данных от Firebase), которая имеет определенный тип данных для ссылки на другие документы (что, к сожалению, у меня еще не было возможности попробовать).
@ GastónSaillén Спасибо за ваше объяснение. Но я использую firestore. У меня появилась идея, как настроить внешние ключи, но я хочу опробовать ссылочный тип данных firestore для установки внешних ключей. .
in order to query all the items posted by a specific user.
Для этого нет необходимости устанавливать user_id в качестве внешнего ключа в каждом опубликованном элементе, а также item_id в коллекции пользователей. Вы можете только добавить новое свойство к объекту элемента с именем postedBy, которое будет содержать в качестве значения идентификатор пользователя. Чтобы отобразить только элементы определенного пользователя, вам нужно запросить базу данных, используя следующий код:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference itemsRef = rootRef.collection("items");
Query query = itemsRef.whereEqualTo("postedBy", user_id);
Существует также другой подход, предполагающий дублирование данных. Когда дело доходит до Firebase, с этой техникой проблем нет. Это довольно распространенная практика, которая называется denormalization, и для этого я рекомендую вам посмотреть это видео, Денормализация - это нормально с базой данных Firebase. Это для базы данных Firebase Realtime, но концепция аналогичным образом применима и к Cloud Firestore.
Другими словами, вы можете создать новую коллекцию, в которой вы можете хранить все элементы, добавленные конкретным пользователем. Структура базы данных должна выглядеть так:
Firestore-root
|
--- users (collecton)
|
--- userId (document)
|
--- userItems (collecton)
|
--- itemId (document)
Когда вы дублируете данные, нужно иметь в виду одну вещь. Так же, как вы добавляете данные, вам необходимо их поддерживать. Другими словами, если вы хотите обновить / определить элемент, вам нужно сделать это везде, где он существует.
Да, уже используется тот же первый метод, который включает в себя установку user_id в новом поле вместе с добавляемыми элементами. Большое спасибо за ваше ясное объяснение. Но знаете ли вы, как использовать ссылочный тип данных? Я просто из любопытства.
Пожалуйста! Как и в официальный документ, вы можете использовать ссылку в этой строке: projects/[PROJECT_ID]/databases/[DATABASE_ID]/documents/[DOCUMENT_PATH].
Если вы считаете, что мой ответ вам помог, примите его. Спасибо!
Спасибо @Alex. Я думал, есть ли другой метод использования ссылочного типа данных для установки и запроса. В любом случае, спасибо
Чем это лучше, чем хранить идентификатор документа в качестве ссылки?