【问题标题】:How can you find something inside cloud Firestore when you don't know the key?当您不知道密钥时,如何在 Cloud Firestore 中找到一些东西?
【发布时间】:2020-02-26 18:58:03
【问题描述】:

现在,考虑一下我有大约一百万用户的 userId(这可能是一个集合)

1234567
1223452
1223454
1223456
1223425
1225451
......
......
......

现在,每个集合都包含文档,看起来像这样

1234567 
  --- userauth 
  ------ email: any123@gmail.com
1223452
  --- userauth 
  ------ email: varun123@gmail.com
......
......
......

现在,如果我想查找具有特定电子邮件 id 的人的 userId(例如:any123@gmail.com),我该怎么做?

对于这个问题,我在云函数内部进行操作。

会比 SQL 更高效吗?

更新:回答我做了这样的事情

class docStore() {
 constructor (firestore) {
  this.store = firestore 
 }

async query(collection, condition) {
        let colRef = this.store.collection(collection)
        if (_.isArray(condition)) {
            condition.forEach(predicate => {
                colRef = colRef.where(predicate.name, predicate.op, predicate.value)
            })
        }

        const results = []
        const snapshot = await colRef.get()
        snapshot.forEach(doc => {
            results.push({data: doc.data(), id:doc.id})
        })
        console.notice(results)
        return results
    }

}

this.storeadmin.firestore()

我的查询是这样的

const checkIfEmailExsist = await docStore.query(SIGNUP_TABLES.userAuth, ['email', '==', userEmail])

这里docStore 高于类,我在其中引用查询

这给了我以下错误

[2019-11-01T13:52:36.873Z](节点:94753) UnhandledPromiseRejectionWarning:错误:参数值 “fieldPath”不是有效的字段路径。路径不能省略。

知道我做错了什么吗?

【问题讨论】:

  • 您查看过how to make queries in Cloud Firestore 吗?另外,您是在云功能中还是在网络上?
  • 我正在使用 firebase 功能,感谢您查看您分享的链接。
  • @Kolban 更新了问题。我知道电子邮件地址,但不知道 userId

标签: javascript node.js firebase google-cloud-platform google-cloud-firestore


【解决方案1】:

感谢您回答您在云函数内部进行操作,因此使用了管理 API。这是how to make a query to firestore的再次链接。

这里有一个简单的函数来演示类似上面的查询(我假设一个名为“用户”的集合):

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

let db = admin.firestore();

exports.doQuery = functions.https.onRequest((request, response) => {
    const queryRef = db.collection('users').where('email', '==', 'any123@gmail.com');

    queryRef.get().then((snap) => {
      if (snap.empty) {
        response.send('no result');
      } else {
        let result = '';
        snap.forEach((doc) => {
          result = result + doc.id + ' => ' + JSON.stringify(doc.data()) + '<br>';
        })
        response.send(result);
      }
    }).catch((err) => { response.send('error'); });

  });

在您的示例中,尽管您表明存在中间 userauth 级别。假设这是一张地图(而不是,比如说,另一个集合或其他东西),您可以使用 FieldPath 让您的查询遍历地图。该查询看起来像这样,并且仍会返回整个用户文档:

    const queryRef = db.collection('userProfiles').where(
      new admin.firestore.FieldPath('userauth','email'), '==', 'any123@gmail.com');

至于效率问题,这种类型的查询(简单相等)在 firestore 中执行将非常有效,因为默认情况下您会获得每个值的索引。更复杂的查询可能会更昂贵,并且需要您create an index。另外,您是only charged for the documents returned(对于空结果集至少有一个文档)。

与 SQL 数据库进行比较当然需要进行实际的性能测试,这是一个更广泛的问题,涉及到您正在执行的查询类型的全部范围、数据库的完整布局、存在哪些索引、您还想从 SQL 数据库中获得 Firestore 未提供的其他功能(例如约束),您是在优化成本、延迟还是其他方面等等。

【讨论】:

  • 假设emailusers 集合文档中的第一级子级。意味着没有像 userauth 对象包装 email 这样的东西。
  • 出色的收获,@SanketPatel。我已经扩展了答案以显示如何使用FieldPath 遍历这样的地图。
  • @robsiemb 稍微更新了这个问题,我试图将 SQL 查询映射到 firestore,但看起来这不是一个好主意。今晚我将酿造一个新鲜的 Api,看看它是否有效,并将其标记为已回答。同时,您能再检查一下问题吗?
  • @SanketPatel 稍微更新了问题,很想听听您的建议
  • 我不确定 '.name'、'.op' 等成员在 foreach 中的来源......看起来你可能只想要 spread operator 而不是 forEach在这种情况下。 predicate.name 似乎是未定义的(而不是字符串或 FieldPath 对象),因此 where 子句不能将其用作有效的 FieldPath。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-30
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 2021-10-31
相关资源
最近更新 更多