[Proposal] Allow paths in ids
See original GitHub issueProposal
Allow paths in ids e.g. project1/-abcdef
so that deep data structures can be supported. Deep structures are often used in Firebase apps and are particularly useful when locking things down via security rules.
Detailed explanation
Without storing within deep paths, it is difficult to write security rules that allow listening for live changes across a subset of records. For example, if you were to have a chat app where messages were stored under the messages collection and secured so that no single user can read all messages:
// data
messages : {
-Xyz: { from: 'user1', to: 'user2', ... },
-Xzz: { from: 'user2', to: 'user3', ... },
}
// rules
"messages": {
".read": false,
"$messageId": {
".read": "auth.uid == data.child('from').val() || ..."
}
This will prevent a realtime query on messages. You cannot do a query on the top level, because “.read” is false. Your current option is to store each message in a hasMany
relationship under user.messages
, or create some other intermediate object with hasMany
links.
If we could use paths in both ids and queries:
// data
messages : {
conversation1: {
-Xyz: { from: 'user1', to: 'user2', conversationId: 'conversation1', ... },
-Xzz: { from: 'user1', to: 'user2', conversationId: 'conversation1', ... },
},
room1: {
-Abc: { to: 'room1', ... },
}
}
// rules
"messages": {
".read": false,
"$conversationId": {
".read": "root.child('rooms').child($roomId).child('members').child(auth.uid).val() == true",
}
Example API
// chat room message
const conversationId = room.get('id');
// private conversation
const conversationId = [me.get('id'), you.get('id')].sort().join('_');
// get messages via a raw firebase query
const messageQuery = this.get('firebase').child(`messages/${conversationId}`).limitToLast(100);
store.query(messageQuery).then(liveArray => {
this.set('model', liveArray);
});
// save new message
const newId = this.get('firebase').push().key;
const message = store.createRecord('message', {
id: `${conversationId}/${newId}`,
roomId: conversationId,
body: 'Hello world',
}).save(); // saves at /messages/:conversationId/:pushId
Breaking changes
The intent is for this to be backwards compatible with the existing API and data structure.
Open questions
- How would relationships be saved in the db? with slashes, replace dots with slashes?
Issue Analytics
- State:
- Created 7 years ago
- Comments:21 (15 by maintainers)
Top GitHub Comments
For me it kinda feels not ember data-ish.
Right now in ember data, the current standard for querying data as shown in the guides should be of this syntax:
Of course, it depends on the adapter if they’ll handle that syntax. But I think it would be nice if emberfire will be as close to it as possible. Like this:
+1 to having a path in the query.
I was also thinking we could help with your situation currently by letting the query know if you’re expecting objects, or links to objects. If it was expecting links to objects you could use it for your structure above.
We could look for
id1: true
and convert this to an async object lookup forstore.findRecord('post', 'id1')
edit: type is probably not the right parameter name, but you get the idea.