什么是firestore参考数据类型适合哪些?

Jür*_*ter 147 firebase google-cloud-firestore

我正在探索新的Firebase Firestore,它包含一个名为的数据类型reference.我不清楚这是做什么的.

  • 它像外键吗?
  • 它可以用来指向位于其他地方的集合吗?
  • 如果reference是实际参考,我可以将它用于查询吗?例如,我可以有一个直接指向用户的引用,而不是将userId存储在文本字段中吗?我可以使用此用户参考进行查询吗?

Ben*_*ane 104

使用Firestore中的引用添加以下对我有用的内容.

正如其他答案所说,它就像一把外键.但是,reference属性不会返回引用doc的数据.例如,我有一个产品列表,其中userRef引用作为产品的属性之一.获取产品列表,为我提供了创建该产品的用户的参考.但它并没有向我提供该参考中用户的详细信息.我之前使用其他后端作为带有指针的服务有一个"populate:true"标志,它给用户提供详细信息而不仅仅是用户的参考ID,这对我来说很有用(希望未来有所改进) ).

下面是我用来设置引用以及获取产品列表集合的示例代码,然后从给定的用户引用ID获取用户详细信息.

在集合上设置引用:

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

获取每个文档的集合(产品)和所有引用(用户详细信息):

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) });
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 首先感谢你的例子.我希望他们将为未来添加"填充:真实".否则保存引用有点毫无意义.只需通过它保存`uid`和引用即可. (43认同)
  • 所以实际上它不像外键.对我来说它基本上什么都没有 - 如果我们不能使用它作为一个真正的外键应该有效,那么有什么指向`reference`? (14认同)
  • 因此,“引用”相对于“字符串”的唯一优势是,您可以直接在引用上调用“ get()”。还不是很有用。希望他们添加一个选项,以使用相应的对象自动填充引用! (8认同)
  • 谢谢你的例子!但是,如果在查询文档时没有"填充"类型的选项,那么存储引用类型的重点是什么?如果有人知道的填充选项,请告诉我. (4认同)
  • 感谢分享!我认为Get部分的第一行有一个拼写错误,它应该是`db.collection('products').get()`.你试过直接获得用户吗?我猜`newItem.userRef.get()`应该工作而不是`db.collection("users").doc(newItem.userRef.id).get()` (3认同)
  • 对我来说,像这样使用它会比它应该有更多的问题。我们可以使用 ref 或添加一些字段,如“userID: string”,这将允许我们以其他方式找到它。我不喜欢 ref 方法的原因是耦合数据模型(无模式),所以你不会干。我认为最好有一个管理集合和映射数据的服务,而不是在单个服务中引用不同的集合。如果数据发生变化,就会出现问题。 (2认同)

Gil*_*ert 68

引用非常像外键.

当前发布的SDK无法存储对其他项目的引用.在项目中,引用可以指向任何其他集合中的任何其他文档.

您可以在查询中使用引用,例如任何其他值:用于过滤,排序和分页(startAt/startAfter).

与SQL数据库中的外键不同,引用对于在单个查询中执行连接没有用.您可以将它们用于依赖查找(看起来像是连接),但要小心,因为每一跳都会导致另一次往返服务器.

  • 顺便说一下,更新[docs](https://firebase.google.com/docs/firestore/manage-data/add-data)以包含添加引用类型的示例可能很有用. (95认同)
  • 我找不到关于此的任何信息?这将改变我的整个数据库结构,我需要了解更多...... (10认同)
  • 请问您可以分享可能的用例吗?是否可以查询该引用中的字段?例如,我有一个'friends`系列列出了我所有的朋友(`friends/myId`).然后,我在另一个文档(`group/groupId`)的`friends`字段中引用该文档.我只想展示那些在这个群体中的朋友,做这样的事情:`where('friends.myId','==',true)`. (9认同)
  • 我需要将所有引用类型更改为字符串,因为查询将始终以引用类型失败.我几乎找不到任何关于如何通过引用类型查询:(如果有人发现如何通过引用类型查询让我知道... (4认同)
  • 你有一个关于如何使用引用查询的例子(最好是在swift中)吗?现在,我可以通过将原始uid存储为字符串来实现,但这似乎不对. (2认同)

Asw*_*mar 23

对于那些寻找通过引用查询的 Javascript 解决方案的人 - 概念是,您需要在查询语句中使用“文档引用”对象

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

(感谢这里的答案:https : //stackoverflow.com/a/53141199/1487867


Vik*_*tha 11

很多答案都提到它只是对另一个文档的引用,但不会返回该引用的数据,但我们可以使用它单独获取数据。

以下是如何在 firebase 版本中使用它的示例JavaScript SDK 9, modular

让我们假设您的 Firestore 有一个名为 的集合products,并且它包含以下文档。

{
  name: 'productName',
  size: 'medium',
  userRef: 'user/dfjalskerijfs'
}
Run Code Online (Sandbox Code Playgroud)

在这里,用户可以引用users集合中的文档。我们可以使用以下代码段来获取产品,然后从引用中检索用户。

import { collection, getDocs, getDoc, query, where } from "firebase/firestore";
import { db } from "./main"; // firestore db object

let productsWithUser = []
const querySnaphot = await getDocs(collection(db, 'products'));
querySnapshot.forEach(async (doc) => {
  let newItem = {id: doc.id, ...doc.data()};
  if(newItem.userRef) {
    let userData = await getDoc(newItem.userRef);
    if(userData.exists()) {
      newItem.userData = {userID: userData.id, ...userData.data()}
    }
    productwithUser.push(newItem);
  } else {
    productwithUser.push(newItem);
  }
});
Run Code Online (Sandbox Code Playgroud)

这里collection, getDocs, getDoc, query, where是与 firestore 相关的模块,我们可以在需要时使用它来获取数据。我们使用products直接从文档返回的用户引用来获取该引用的用户文档,使用以下代码,

let userData = await getDoc(newItem.userRef);
Run Code Online (Sandbox Code Playgroud)

要了解有关如何使用模块化版本 SDK 的更多信息,请参阅官方文档以了解更多信息。

  • 请注意,虽然对裁判的每个请求都将被计入阅读 (3认同)

Pav*_*tov 9

根据#AskFirebase https://youtu.be/Elg2zDVIcLo?t=276 目前的主要用例是 Firebase 控制台 UI 中的链接

  • 这仍然不起作用 - 至少我无法在用户界面中发现它:) (12认同)
  • 为什么要为 Firebase 控制台 UI 中链接的主要目的构建数据类型? (2认同)

小智 5

如果您不使用参考数据类型,则需要更新每个文档

例如,您有 2 个集合“类别”“产品” ,并且您将类别中的类别名称“水果”存储到产品“苹果”“柠檬”的每个文档中,如下所示。但是,如果您更新categories中的类别名称“Fruits”,则还需要更新products“Apple”“Lemon”的每个文档中的类别名称“Fruits”

collection | document | field

categories > 67f60ad3 > name: "Fruits"
Run Code Online (Sandbox Code Playgroud)
collection | document | field

  products > 32d410a7 > name: "Apple", category: "Fruits"
             58d16c57 > name: "Lemon", category: "Fruits"
Run Code Online (Sandbox Code Playgroud)

但是,如果您将类别“水果”的引用存储到产品“苹果”“柠檬”的每个文档中,则在更新类别名称时不需要更新“苹果”“柠檬”的每个文档类别中的"水果" :

collection | document | field

  products > 32d410a7 > name: "Apple", category: categories/67f60ad3
             58d16c57 > name: "Lemon", category: categories/67f60ad3
Run Code Online (Sandbox Code Playgroud)

这就是引用数据类型的优点。

  • 讨论的重点并不是存储静态名称与“类似外键”的 id;而是存储静态名称。而是使用文档引用与仅使用文档 ID 作为字符串的好处。 (9认同)