可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I thought I read that you can query subcollections with the new Firebase Firestore, but I don\'t see any examples. For example I have my Firestore setup in the following way:
- Dances [collection]
- danceName
- Songs [collection]
How would I be able to query \"Find all dances where songName == \'X\'\"
回答1:
This is a feature which does not yet exist. It\'s called a \"collection group query\" and would allow you query all songs regardless of which dance contained them. This is something we intend to support but don\'t have a concrete timeline on when it\'s coming.
The alternative structure at this point is to make songs a top-level collection and make which dance the song is a part of a property of the song.
回答2:
What if you store songs as an object instead of as a collection? Each dance as, with songs as a field: type Object (not a collection)
{
danceName: \"My Dance\",
songs: {
\"aNameOfASong\": true,
\"aNameOfAnotherSong\": true,
}
}
then you could query for all dances with aNameOfASong:
db.collection(\'Dances\')
.where(\'songs.aNameOfASong\', \'==\', true)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, \" => \", doc.data());
});
})
.catch(function(error) {
console.log(\"Error getting documents: \", error);
});
回答3:
UPDATE
Now Firestore supports array-contains
Having these documents
{danceName: \'Danca name 1\', songName: [\'Title1\',\'Title2\']}
{danceName: \'Danca name 2\', songName: [\'Title3\']}
do it this way
collection(\"Dances\")
.where(\"songName\", \"array-contains\", \"Title1\")
.get()...
@Nelson.b.austin Since firestore does not have that yet, I suggest you to have a flat structure, meaning:
Dances = {
danceName: \'Dance name 1\',
songName_Title1: true,
songName_Title2: true,
songName_Title3: false
}
Having it in that way, you can get it done:
var songTitle = \'Title1\';
var dances = db.collection(\"Dances\");
var query = dances.where(\"songName_\"+songTitle, \"==\", true);
I hope this helps.
回答4:
As stated by Gil Gilbert, it seems as if collection group queries is currently in the works. In the mean time it is probably better to use root level collections and just link between these collection using the document UID\'s.
For those who don\'t already know, Jeff Delaney has some incredible guides and resources for anyone working with Firebase (and Angular) on AngularFirebase.
Firestore NoSQL Relational Data Modeling - Here he breaks down the basics of NoSQL and Firestore DB structuring
Advanced Data Modeling With Firestore by Example - These are more advanced techniques to keep in the back of your mind. A great read for those wanting to take there Firestore skills to the next level
回答5:
It could be better to use a flat data structure.
The docs specify the pros and cons of different data structures on this page.
Specifically about the limitations of structures with sub-collections:
You can\'t easily delete subcollections, or perform compound queries across subcollections.
Contrasted with the purported advantages of a flat data structure:
Root-level collections offer the most flexibility and scalability, along with powerful querying within each collection.
回答6:
You can always search like this:-
this.key$ = new BehaviorSubject(null);
return this.key$.switchMap(key =>
this.angFirestore
.collection(\"dances\").doc(\"danceName\").collections(\"songs\", ref =>
ref
.where(\"songName\", \"==\", X)
)
.snapshotChanges()
.map(actions => {
if (actions.toString()) {
return actions.map(a => {
const data = a.payload.doc.data() as Dance;
const id = a.payload.doc.id;
return { id, ...data };
});
} else {
return false;
}
})
);
回答7:
var songs = []
db.collection(\'Dances\')
.where(\'songs.aNameOfASong\', \'==\', true)
.get()
.then(function(querySnapshot) {
var songLength = querySnapshot.size
var i=0;
querySnapshot.forEach(function(doc) {
songs.push(doc.data())
i ++;
if(songLength===i){
console.log(songs
}
console.log(doc.id, \" => \", doc.data());
});
})
.catch(function(error) {
console.log(\"Error getting documents: \", error);
});
回答8:
Query limitations
Cloud Firestore does not support the following types of queries:
Queries with range filters on different fields.
Single queries across multiple collections or subcollections. Each query runs against a single collection of documents. For more
information about how your data structure affects your queries, see
Choose a Data Structure.
- Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
- Queries with a != clause. In this case, you should split the query into a greater-than query and a less-than query. For example, although
the query clause where(\"age\", \"!=\", \"30\") is not supported, you can
get the same result set by combining two queries, one with the clause
where(\"age\", \"<\", \"30\") and one with the clause where(\"age\", \">\", 30).