I want to create a database structure for my realtime database in firebase. Right now I have list and those list have sublist. Those sublist have products and users.
To get the users in a sublist I defined his own object
"SubListUser" : {
"SubListId1" : {
"User1Id" : {
"username" :"String",
"photoUrl" : "String"
},
"User2Id" : {
"username" :"String",
"photoUrl" : "String"
}
"ListId": "ListId1"
}
And to get the products I have this JSON object
"SubListProducts" : {
"SubListId1" : {
"Products" : {
"ProductId1" : {
"name" : "String",
"productPhotoUrl" : "String"
}
"ListId": "ListId1"
}
Those subLists are inside other lists. To know the sublist in a list I have this object
{ "Lists":
"List1": {
"subList1" : "SubListId1",
"subList2" : "SubListId2",
}
}
If I want to know the products/users of a sublist is this okay? Because if I want to know the products/users I have to do 2 finds first find the list with their sublist, and then find the products/users of that sublist.
I don't know if this is good or should I redo my database?
Related
I am trying to write a firebase rule that checks to see if you have access to a child of one node by checking the data of another node. The issue I am having is accessing the other node's data because it is stored under an AutoId. How would I access the data under the AutoId?
Here is my database structure:
{
"products" : {
"Product001" : {
"ownerId" : "User002",
"productName": "Name"
},
"product002" : {
"ownerId" : "User001",
"productName": "Name"
}
},
"shares" : {
"share001" : {
"accepted" : true,
"ownerId" : "User002",
"productId" : "Product001",
"userEmail" : "example#email.com"
},
"share002" : {
"accepted" : true,
"ownerId" : "User001",
"productId" : "Product002",
"userEmail" : "email#exaple.com"
}
},
"users" : {
"User001" : {
"email" : "example#email.com",
"firstName" : "John",
"lastName" : "Smith"
},
"User002" : {
"email" : "email#example.com",
"firstName" : "John",
"lastName" : "Smith"
}
}
}
Here is the section of the rules that is causing me a problem:
"products":{
"$productId":{
".read":"root.child('shares').child($shareId).child('productId').val() === $productId && root.child('shares').child($shareId).child('ownerId').val() === auth.uid",
".write":"root.child('shares').child($shareId).child('productId').val() === $productId && root.child('shares').child($shareId).child('ownerId').val() === auth.uid"
}
}
Essentially, a user is only allowed to access a premises if they are in a share that contains their information.
Thank you for any advice.
There is no way in security rules to query or search another node, as the performance of that would be way too unreliable. So in your current data model it is not possible to allow the user access to a product if they have any shares for that product.
You'll need to have a list somewhere in a knowable path of the products the user can read. For example, say that you keep a list of the products the user is interested in:
"interests" : {
"User001" : {
"Product001": true,
"Product002": true
},
Now you can allow the user access to all products they follow with:
"products":{
"$productId":{
".read":"root.child('interests').child(auth.uid).child($productId).exists()",
".write": ...
}
}
I have an existing avro schema that contains a field with a nested map of map of a record type (let's call it RecordA for now). I'm wondering if it's possible to add a new record type, RecordB, to this nested map of maps while maintaining FULL_TRANSIENT compatibility?
My thinking was that as long as the inner maps gets defaulted to an empty map it still adheres to the schema so it's backwards/forward compatible.
I've tried to redefine the type map<map<RecordA>> maps to map<map<union{RecordA, RecordB}>> maps in an .avdl file, but the schema registry is telling me this is not compatible.
I've also tried to default each map individually to an empty map ({ }) in a generated .avsc file, but schema registry says that's incompatible as well.
I do want to acknowledge that I know map<map<..>> is a bad practice, but what's been done has been done.
Registered Schema (original) .avdl:
record Outer {
map<map<RecordA>> maps;
}
record RecordA {
string value;
string updateTime;
}
Attempt with .avdl:
record Outer {
map<map<union{RecordA, RecordB}>> maps = {};
}
record RecordA {
string value;
string updateTime;
}
record RecordB {
union{null, array<string>} values = null;
union{null, string} updateTime = null;
}
Attempt with .avsc:
{
"name" : "maps",
"type" : {
"type" : "map",
"values" : {
"type" : "map",
"values" : [ {
"type" : "record",
"name" : "RecordA",
"fields" : [ {
"name" : "value",
"type" : "string"
}, {
"name" : "updateTime",
"type" : "string"
} ],
"default": { }
}, {
"type" : "record",
"name" : "RecordB",
"fields" : [ {
"name" : "value",
"type" : [ "null", "string" ],
"default" : null
}, {
"name" : "values",
"type" : [ "null", "string" ],
"default" : null
}, {
"name" : "updateTime",
"type" : [ "null", "string" ],
"default" : null
} ],
"default": { }
} ]
}
},
"default" : { }
}
The end goal is to have a map of maps to a record who has a field that can either be a string or array<string>. The original schema was registered to a schema-registry where the field has type string with no union {} with null or a default, so I believe the map needs to be map to a union of types with either version of the field.
Each try has returned the following from the schema-registry compatibility API
{
"is_compatible": false
}
Any insight would be very much appreciated!
New Dgraph user wondering if anyone can provide me with an example recursive count and sum query to help get me going.
The data looks like this (there are more predicates, but left out for simplicity):
{
"uid" : <0x1>,
"url" : "example.com",
"link" : [
{
"uid" : <0x2>,
"url" : "example2.com",
"link" : [
{
"uid" : <0x4>,
"url" : "example4.com",
"link" : [
{
"uid" : <0x6>,
"url" : "example6.com",
"link" : [
{
etc...
}
]
}
]
},
{
"uid" : <0x5>,
"url" : "example5.com",
}
]
},
{
"uid" : <0x2>,
"url" : "example2.com",
"link" : [
{
etc ....
}
},
]
}
Just a home page with n-links which each have n-links and the depth, obviously, can vary. Just hoping for a good example of how to count all the links for each url and sum them up. I will add different filters to the query at some point, but just wanting to see a basic query to help get me going. Thanks.
I use Firebase and AngularFire4 in a web application. The model is relatively simple, but I am having troubles in finding the right way to design it.
I have two collections: places and countries like the following:
Places
"places" : {
"-Kjx7NhHnyZNIZbxvzx4" : {
"name" : "Dereck beer",
"type" : "Bar"
"location" : {
"cityName" : "Kagoshima",
"country" : {
"code" : "JP",
"id" : 110,
"name" : "Japan"
},
"streetName" : "892-0842 Higashisen"
},
"modifiedOn": 121211321321
}
//... More data here...
}
Countries
"countries" : {
"110" : {
"code" : "JP",
"id" : 110,
"name" : "Japan"
}
}
At the moment in the web application I display the list of places and I can navigate to the detail view of each place. I can also display the countries where the places belong to (I create a new entry in countries collection, if not existing already, when a new place is created/updated).
However I would like to filter the places by some properties, like by type for instance. I tried with the following query, from AngularFire docs, but it does not work:
constructor(private db: AngularFireDatabase) {
var query = {
orderByChild: 'modifiedOn',
equalTo: {
value: 'Bar',
key: 'type' }
};
this.db.list("/places", query).subscribe( data => {
//All places are returned, and not only the one of type = "Bar"
});
}
If possible, I would like to avoid this approach and to replicate excessively my collections just for being able to query them.
it should be
var query = {
orderByChild: 'type',
equalTo: 'Bar'
};
orderByChild and equalTo is a pair in firebase, it's different from sql query
I am trying to check, if two objects have at least one common child. In the following example I want to be able to be control, if people can read org.money.value.
The right to read is determined by comparing the children of org.keys and users.{auth.uid}.keys. If there is a common key, reading would be allowed.
Database JSON:
{
"org" : {
"keys" : {
"red" : {
"value" : "..."
},
"blue" : {
"value" : "..."
}
},
"money" : {
"value" : "..."
}
},
"users" : {
"John" : { // in reality John == auth.uid of a user
"keys" : {
"red" : {
"value" : "..."
}
}
},
"Alice" : { // in reality Alice == auth.uid of a user
"keys" : {
"green" : {
"value" : "..."
}
}
}
}
}
Rules:
"rules:"{
"org" : {
"money" : {
// can read if "org.keys" and "users.auth.uid.keys"
// have at least one common child name.
// With the above data reading would be allowed for John,
// but not for Alice.
".read" : what to write here?
}
}
}
Is it possible to make this work?
By the way, the organization does not know the auth.uid of users.
I can't think of any way that you could do this determination in the JSON rules with your current database structure. I would suggest altering your structure to allow for this type of read determination. Here's a potential solution I came up with, which will require more filtering on client side:
When you create a new user key, loop through the org keys to see if it is already contained there. If so, add a BOOL to the user object, perhaps "canReadMoney" and set it to true. Then, your rule for money would look something like this:
"rules:"{
"org" : {
"money" : {
".read" : "root.child('users').child(auth.uid).child('canReadMoney').val==true"
}
}
}
another solution could be storing endpoint in the database like this
usersShareOrg
{
"John": { "Org" : true }
"Alice": {"Org": false}
}
and these values would be calculated and stored every time you added new user or org.keys entity.