Javascript Firestore:按字段索引和按参数筛选

Javascript Firestore:按字段索引和按参数筛选,javascript,database,firebase,google-cloud-firestore,nosql,Javascript,Database,Firebase,Google Cloud Firestore,Nosql,我对Firebase有一个特别的问题,就是我很难理解Firebase复合查询,也许有人比我更了解数据查询 形势 我有一个设备和位置的图形数据库,其中有一个查找表(deviceAtLocation),用于设备添加到位置的时间。使用设备ID和位置,我可以通过如下查询查找当前位置或设备: Type Device { id: ID! ... } Type Location{ id: ID! ... } Type deviceAtLocation{ id: ID! timestamp: ID! dev

我对Firebase有一个特别的问题,就是我很难理解Firebase复合查询,也许有人比我更了解数据查询

形势

我有一个设备和位置的图形数据库,其中有一个查找表(deviceAtLocation),用于设备添加到位置的时间。使用设备ID和位置,我可以通过如下查询查找当前位置或设备:

Type Device {
id: ID!
...
}

Type Location{
id: ID!
...
}

Type deviceAtLocation{
id: ID!
timestamp: ID!
deviceId: ID!
location: ID
...
}


const currentLocation = await db
       .collection("deviceAtLocation)
       .where("deviceId", "==", ARG)
       .orderBy("timestamp","desc)
       .limit(1)
       .get()
       .then((i)=>i.docs.map((d)=>d.data())[0])
这是伟大的,工作真的很好。但是问题来了,我想找出目前在一个位置的所有设备

问题

当我想查找某个位置的所有设备时,我遇到了一个问题,即必须调用整个查找表两次,首先查找当前位置的所有设备,然后查看其当前位置是否与我正在搜索的位置匹配。像这样:

const devicesAtLoc = await db
       .collection("deviceAtLocation)
       .where("locationId", "==", ARG)
       .get()
       .then((i)=>i.docs.map((d)=>d.data().deviceId)

devicesAtLoc.map(async(device)=>{
        await db
              .collection("deviceAtLocation)
              .where("deviceId", "==", device)
              .orderBy("timestamp","desc)
              .limit(1)
              .get()
              .then((i)=>i.docs.map((d)=>d.data())[0])
        }).filter((result)=>result === ARG)
我原以为这会起作用,但它仍然返回错误。我的大脑在试图思考承诺和文件时有点紧张,但仍然无法得到任何好的结果

更好的解决方案?

基本上,我正在寻找一种更好的方法来索引查找表中的所有文档,然后提取最新的文档,看看它是否位于我正在查看的位置。我不确定是否有办法按locationId编制索引,然后只查询组中最近的条目

任何帮助都将不胜感激

更新

经过大量修改后,这是两次调用查找的代码的工作版本:

async devices(par, arg) {
      try {
        //This needs work, I'm not sure how to get all the devices without duplicates
        const devicesAtLocation = await db
          .collection('deviceAtLocation')
          .where('locationId', '==', par.id)
          .orderBy('timestamp', 'desc')
          .get()
          .then((i) => i.docs.map((atLoc) => atLoc.data().deviceId));

        if (!devicesAtLocation)
          return new ValidationError('No device(s) found');

        const filtered = await devicesAtLocation.filter(async (d) => {
          const deviceAtLoc = await db
            .collection('deviceAtLocation')
            .where('deviceId', '==', d)
            .orderBy('timestamp', 'desc')
            .limit(1)
            .get()
            .then((i) => i.docs[0].data());
          deviceAtLoc.locationId === par.id ? true : false;
        });
        const devices = await filtered.map(
          async (d) =>
            await db
              .collection('mimirDevice')
              .doc(d)
              .get()
              .then((i) => i.data())
        );

        return (await devices) || new ValidationError('No device(s) found');
      } catch (error) {
        throw new ApolloError(error);
      }
    },