Для чего нужен Firebase Firestore 'Reference'?

189

Я просто изучаю новый Firebase Firestore, и он содержит тип данных с именем reference. Мне не ясно, что это делает.

  • Это как внешний ключ?
  • Можно ли использовать его для указания на коллекцию, которая находится где-то еще?
  • Если referenceэто реальная ссылка, могу ли я использовать ее для запросов? Например, я могу иметь ссылку, которая указывает непосредственно на пользователя, вместо того, чтобы хранить userId в текстовом поле? И могу ли я использовать эту ссылку для запроса?
Юрген Брандштеттер
источник
18
Я думаю, что это видео от команды Firebase разбивает его для вас: youtube.com/watch?v=Elg2zDVIcLo (смотрите с 4:36)
Адарш
10
youtu.be/Elg2zDVIcLo?t=276
Тревор

Ответы:

91

Ссылки очень похожи на внешние ключи.

Выпущенные в настоящее время SDK не могут хранить ссылки на другие проекты. В рамках проекта ссылки могут указывать на любой другой документ в любой другой коллекции.

Вы можете использовать ссылки в запросах, как и любое другое значение: для фильтрации, упорядочения и подкачки (startAt / startAfter).

В отличие от внешних ключей в базе данных SQL, ссылки не полезны для выполнения объединений в одном запросе. Вы можете использовать их для зависимых поисков (которые выглядят как соединения), но будьте осторожны, потому что каждый прыжок приведет к очередному обращению к серверу.

Гил Гилберт
источник
9
Пожалуйста, вы можете поделиться возможными вариантами использования? Можно ли запросить поля в этой ссылке? Например, у меня есть friendsколлекция, в которой перечислены все мои друзья ( friends/myId). Затем я ссылаюсь на этот документ в friendsполе другого документа ( group/groupId). Я хотел бы показать только моих друзей , которые находятся в этой группе, делать что - то вроде этого: where('friends.myId', '==', true).
Будет
108
Кстати, может быть полезно обновить документы, чтобы включить пример добавления ссылочного типа.
Будет
11
Я не могу найти информацию об этом? Это изменит всю структуру моей базы данных, мне нужно знать больше ...
Рубен
3
у вас есть пример (желательно в swift) о том, как сделать запрос, используя ссылку? сейчас я могу сделать это, сохранив необработанный uid в виде строки, но это не так.
Микки Чонг
6
Мне нужно изменить все мои ссылочные типы на строки, потому что запрос всегда будет терпеть неудачу с ссылочным типом. Я буквально не могу найти ничего о том, как сделать запрос по ссылочному типу :(, если кто-нибудь узнает, как сделать запрос по ссылочным типам, дайте мне знать ...
Сэм Трент,
133

Добавляя ниже, что работает для меня, используя ссылки в Firestore.

Как говорят другие ответы, это как внешний ключ. Ссылочный атрибут не возвращает данные справочного документа. Например, у меня есть список продуктов со ссылкой на userRef в качестве одного из атрибутов продукта. Получение списка продуктов дает мне ссылку на пользователя, который создал этот продукт. Но это не дает мне детали пользователя в этой ссылке. Я использовал другой бэкэнд в качестве сервисов с указателями, у которых до этого был флаг «populate: true», который возвращает данные пользователя, а не просто ссылочный идентификатор пользователя, что было бы здорово иметь здесь (надеюсь, в будущем улучшении). ).

Ниже приведен пример кода, который я использовал для задания ссылки, а также для получения списка продуктов, а затем для получения сведений о пользователе по указанному идентификатору ссылки.

Установить ссылку на коллекцию:

let data = {
  name: 'productName',
  size: 'medium',
  userRef: db.doc('users/' + firebase.auth().currentUser.uid)
};
db.collection('products').add(data);

Получить коллекцию (продукты) и все ссылки на каждый документ (данные пользователя):

db.collection('products').get()
    .then(res => {
      vm.mainListItems = [];
      res.forEach(doc => {
        let newItem = doc.data();
        newItem.id = doc.id;
        if (newItem.userRef) {
          newItem.userRef.get()
          .then(res => { 
            newItem.userData = res.data() 
            vm.mainListItems.push(newItem);
          })
          .catch(err => console.error(err));
        } else {
          vm.mainListItems.push(newItem);  
        }

      });
    })
    .catch(err => { console.error(err) });

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

Бен Кокрейн
источник
3
Спасибо, что поделился! Я думаю, что в первой строке Get part есть опечатка, и так и должно быть db.collection('products').get(). Вы пытались получить пользователя напрямую? Я думаю, newItem.userRef.get()должно работать вместоdb.collection("users").doc(newItem.userRef.id).get()
Сергей Нефедьев
53
Прежде всего спасибо за пример. Я надеюсь, что они добавят «населить: правда» на будущее. В противном случае сохранение ссылки несколько бессмысленно. То же самое можно было бы сделать, просто сохранив uidссылку и ссылку через него.
Юрген Брандштеттер
4
Спасибо за пример! Но какой смысл хранить ссылочный тип, если при запросе документа нет опции «заполнить»? Если есть какой-либо вариант, о котором кто-либо знает, пожалуйста, дайте мне знать.
Харшил Шах
18
Так что на самом деле это не похоже на внешний ключ. Для меня это в принципе ничего не значит - какой смысл иметь, referenceесли мы не можем использовать его как настоящий внешний ключ, который должен работать?
Жан Д'Арм
14
Таким образом, единственное преимущество referenceнад a stringзаключается в том, что вы можете get()напрямую обращаться к ссылке. Пока не очень полезно. Надеюсь, они добавят возможность автоматически заполнять ссылки соответствующими объектами!
Морглер
16

Для тех, кто ищет решение Javascript для запроса по ссылке - концепция такова, что вам нужно использовать объект «ссылка на документ» в операторе запроса

teamDbRef = db.collection('teams').doc('CnbasS9cZQ2SfvGY2r3b'); /* CnbasS9cZQ2SfvGY2r3b being the collection ID */
//
//
db.collection("squad").where('team', '==', teamDbRef).get().then((querySnapshot) => {
  //
}).catch(function(error) {
  //
});

(Престижный ответ здесь: https://stackoverflow.com/a/53141199/1487867 )

Асвин Кумар
источник