In Firebase, you can query using a single value or a value range, so constructing a single query to obtain items matching several keywords is not going to be possible. However, you could arrange your database so that you could easily query or a single keyword. You'd then need to combine several queries, etc.
You could arrange your data like this:
{
"items": {
"item1_id": {
"brand_id": ...,
"itemName": ...,
"price": ...,
"keywords": {
"black": true,
"t-shirt": true
}
}
}
}
However, as explained in this answer, you would need to define an index for each keyword. To allow for efficient keyword-based queries, you could create your own mapping of keywords to items:
{
"items": {
"item1_id": {
"brand_id": ...,
"itemName": ...,
"price": ...,
"keywords": {
"black": true,
"t-shirt": true
}
}
},
"keywords": {
"black": {
"item1_id": true
},
"t-shirt": {
"item1_id": true
}
}
}
The query for a keyword would be something like this:
let keyword = "black";
database.ref(`keywords/${keyword}`).once("value", (snapshot) => {
snapshot.forEach((idSnapshot) => {
database.ref(`items/${idSnapshot.key}`).once("value", (itemSnapshot) => {
console.log(JSON.stringify(itemSnapshot.val()));
});
});
});
Having to maintain your own mapping of keywords to items is a little painful, but the queries will be fast. Also, Firebase's multi-location updates can make maintaining the keywords mapping a little easier. To create an item:
database.ref().update({
"items/item1_id": {
"brand_id": ...,
"itemName": ...,
"price": ...,
"keywords": {
"black": true,
"t-shirt": true
}
},
"keywords/black/item1_id": true,
"keywords/t-shirt/item1_id": true
});
To change an item's keywords (remove black
, add blue
and leave t-shirt
untouched):
database.ref().update({
"items/item1_id/keywords": {
"black": null,
"blue": true
},
"keywords/black/item1_id": null,
"keywords/blue/item1_id": true
});
And to delete an item:
database.ref().update({
"items/item1_id": null,
"keywords/blue/item1_id": null,
"keywords/t-shirt/item1_id": null
});