问题
I have the following structure within my firebase realtime database:
- artists
- ArtistID
- name
- listOfPaintings
- PaintingID1
- PaintingID2
- ArtistID
- paintings (there can be
- PaintingID1
- copies
- price
- PaintingID2
- copies
- price
- ...
- PaintingIDX
- copies
- price
- PaintingID1
Now I want to listen for changes of specific paintingIDs and specific ArtistIDs. For example I want to listen to PaintingID1, PaintingID6, PaintingID7, PaintingID11.
My repository code so far:
override fun observeThisPainting(painting: Painting, receiveDataFromBackendCallback: DataFromBackendCallback<Painting>) {
this.receiveDataFromBackendCallback = receiveDataFromBackendCallback
val myRef = database.child("paintings").child(painting.paintingId)
myRef.addValueEventListener(this)
}
override fun onDataChange(snapshot: DataSnapshot) {
val painting = snapshot.getValue(Painting::class.java)
painting?.let { receiveDataFromBackendCallback.onSuccess(it) }
}
override fun onCancelled(error: DatabaseError) {
}
- Is the architecture of my RTDBs right? In my first attempt I saved all paintings inside the artist listOfPaintings. Now I only save the keys for them there.
- How can I achieve to listen to a subset of objects of a specific node from my viewmodel? (I know how to listen to all items of the paintings node, but I want to know if there is a way to listen to speficic items of this node)
Thanks for your ideas!
回答1:
It seems that you're nesting multiple different types of data under a single root node, which the Firebase documentation on structuring data recommends against. I'd usually expect three top-level nodes, in a JSON like this:
Artists: {
"ArtistId1": { name: "...", otherdata... },
"ArtistId2": { name: "...", otherdata... }
},
ArtistPaintings: {
"ArtistId1": {
"Painting1": true,
"Painting3": true
},
"ArtistId2": {
"Painting2": true,
"Painting4": true
}
},
Paintings: {
"Painting1": { ... },
"Painting2": { ... },
"Painting3": { ... },
"Painting4": { ... },
}
With the above you can show a list of all artist names, without also having to download all he painting IDs of all artists.
Then when the user selects an artist, you can load the painting IDs and then the paintings for that artist. If helpful, you can store something more meaningful than the true
, like the painting's title, or a subset of its metadata, so that you can show a list of paintings without further loads.
And if you have a situation where you might also need to look up the artist(s) for a painting, you'll typically add a fourth top-level node PaintingArtists
.
For more on this see my answer to Many to Many relationship in Firebase.
On your second question (please don't put multiple questions in a single post in the future): the only way to listen to a subset of nodes is through a query. So for example if you want to listen to all paintings of a certain price, you'd perform a query on the price.
If you want to listen to all paintings of a certain artist, your options are to:
- Include the Artist ID in each painting, and use a query. This sort of data duplication is very common when using NoSQL databases, as you often end up modifying your data model as you implement additional use-cases in your app.
- Reach the painting IDs for the artist from
/ArtistPaintings
and then use a separate listener for each painting. This is not nearly as slow/resource intensive as you may think, as Firebase pipelines the requests over a single socket.
To learn more about NoSQL data modeling in general and Firebase in particular, read NoSQL data modeling, watch Firebase for SQL developers, and possibly Getting to know Cloud Firestore (the latter is for Cloud Firestore, but many of the mechanisms apply to Realtime Database too).
来源:https://stackoverflow.com/questions/65663123/firebase-realtime-database-how-to-listen-to-a-specific-subset-of-items-of-a-nod