我正在使用带有Firebase数据库的node-express JS编写Rest API。在Firebase中,我有两个集合,例如:
Bin (binName, binLocaton, hardwareId)
BinsInformation (date, payloadFields { hardwareId, levle })
如何根据字段hardwareId
加入这两个收藏集?
I would like to join to collections like two tables in MySQL.
Ex. "SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id "
Like the above MySQL query i would like join my two collections "Bin" and "BinInformation".
如果我加入具有特定ID的单个文档,则会给出正确的输出。但是当我试图加入两个集合中的所有文档时 与一个单独的查询,它给出了“异步错误”。
这是我的收藏集:
Bins:
[
{
AreaID: "ZYwQHIrZPEDd359e6WRf"
Capacity: "123"
Latitude: "17.658745"
LocationName: "testing"
Longitude: "78.9874545"
hardwareid: "4321"
},
{
AreaID: "ZYwQHIrZPEDd359e6WRf"
Capacity: "123"
Latitude: "17.658745"
LocationName: "testing"
Longitude: "78.9874545"
hardwareid: "5432"
}
]
BinInformation:
[
{
date: September 24, 2018 at 12:00:00 AM UTC+5:30,
payload_fields: {
hardwareid: "4321"
level : 60
}
},
{
date: September 24, 2018 at 12:00:00 AM UTC+5:30,
payload_fields: {
hardwareid: "5432"
level : 23
}
}
]
在这里,我需要获取所有具有相应BinInformation的Bin。我的代码是这样
app.get('/twoColectionJoin', asyncHandler( async (req, res, next) => {
console.log('await');
try {
let allDocs = [];
const snapshot = await db.collection('Bins').get();
let i = 0;
snapshot.forEach( async (doc) => {
let dummyDoc = doc.data();
const details = await getBinDet(dummyDoc.hardwareid);
dummyDoc.id = doc.id;
dummyDoc.det = details;
allDocs.push(dummyDoc);
i++;
console.log(allDocs);
});
res.status(200).send(allDocs);
}
catch(e){
next(e);
}
}) );
async function getBinDet(hardwareid){
let dummyDoc = {};
return new Promise(function(resolve, reject){
try{
setTimeout(function(){
db.collection('BinsInformation')
.where('payload_fields.hardwareid', '==', hardwareid)
.limit(1).get()
.then(snap => {
snap.forEach(element => {
//return element.data();
dummyDoc = element.data();
});
resolve(dummyDoc);
})
.catch(err2 => {
reject(err2);
});
}, 300);
}catch(err){
console.log(err);
}
});
}
预期输出:
[
{
AreaID: "ZYwQHIrZPEDd359e6WRf"
Capacity: "123"
Latitude: "17.658745"
LocationName: "testing"
Longitude: "78.9874545"
hardwareid: "4321",
det: {
date: September 24, 2018 at 12:00:00 AM UTC+5:30,
payload_fields : {
hardwareid: "4321"
level : 60
}
}
},
{
AreaID: "ZYwQHIrZPEDd359e6WRf"
Capacity: "123"
Latitude: "17.658745"
LocationName: "testing"
Longitude: "78.9874545"
hardwareid: "5432",
det: {
date: September 24, 2018 at 12:00:00 AM UTC+5:30,
payload_fields: {
hardwareid: "5432"
level : 23
}
}
}
]
但是结果输出是:[]
答案 0 :(得分:1)
将SQL查询转换为Firebase查询不是1:1。而且,如果您尝试在Firebase上执行典型的SQL查询,则Firebase是不适合您的错误数据库(NoSQL)。
使用您上面发布的数据结构,一个完整的示例如下:
const express = require("express");
const admin = require("firebase-admin");
const serviceAccount = require("./serviceAccountKey.json");
const app = express();
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://example.firebaseio.com"
});
const db = admin.firestore();
async function joinsCollectionsHandler(req, res) {
const binsRef = await db.collection("bins").get();
const binData = binsRef.docs.map(doc => doc.data());
const binsInfoRef = await db.collection("bin-information").get();
const binInfoData = binsInfoRef.docs.map(doc => doc.data());
const data = binData.map(bin => {
const { hardwareId } = bin;
const det = binInfoData.filter(
doc => doc.payloadFields.hardwareId === hardwareId
);
return { ...bin, det };
});
res.json(data);
}
app.get("/twoColectionJoin", joinsCollectionsHandler);
app.listen(3000, () => console.log("Started on 3000"));
最终结果是:
[
{
"latitude": "17.658745",
"locationName": "testing",
"longitude": "78.9874545",
"areaId": "ZYwQHIrZPEDd359e6WRf",
"hardwareId": "5432",
"capacity": "123",
"det": [
{
"date": "2018-09-23T18:30:00.000Z",
"payloadFields": {
"level": 23,
"hardwareId": "5432"
}
}
]
},
{
"capacity": "123",
"areaId": "ZYwQHIrZPEDd359e6WRf",
"latitude": "17.658745",
"hardwareId": "4321",
"locationName": "testing",
"det": [
{
"date": "2018-09-23T18:30:00.000Z",
"payloadFields": {
"level": 60,
"hardwareId": "4321"
}
}
]
}
]
我已经在本地测试过,并且工作正常。如果您有任何问题,请告诉我。