development

Firestore 쿼리 하위 컬렉션

big-blog 2020. 8. 28. 07:54
반응형

Firestore 쿼리 하위 컬렉션


새로운 Firebase Firestore를 사용하여 하위 컬렉션을 쿼리 할 수 ​​있다고 읽었지만 예제가 보이지 않습니다. 예를 들어 다음과 같은 방식으로 Firestore를 설정했습니다.

  • 춤 [컬렉션]
    • danceName
    • 노래 [컬렉션]
      • 노래 제목

"SongName == 'X'인 모든 춤 찾기"를 어떻게 쿼리 할 수 ​​있습니까?


업데이트 2019-05-07

오늘 우리는 컬렉션 그룹 쿼리를 출시 했으며이를 통해 하위 컬렉션 을 쿼리 할 수 ​​있습니다.

예를 들어 웹 SDK에서 :

db.collectionGroup('Songs')
  .where('songName', '==', 'X')
  .get()

컬렉션 경로의 마지막 부분이 'Songs'인 모든 컬렉션의 문서와 일치합니다.

원래 질문은 songName == 'X'인 댄스 를 찾는 것이 었는데 여전히 직접 불가능하지만 일치하는 각 노래에 대해 부모를로드 할 수 있습니다.

원래 답변

이것은 아직 존재하지 않는 기능입니다. 이를 "컬렉션 그룹 쿼리"라고하며 어떤 댄스에 포함되었는지에 관계없이 모든 노래를 쿼리 할 수 ​​있습니다. 이것은 우리가 지원하려는 것이지만 그것이 언제 오는지에 대한 구체적인 일정이 없습니다.

이 시점에서 대체 구조는 노래를 최상위 컬렉션으로 만들고 노래가 노래 속성의 일부인 댄스를 만드는 것입니다.


지금 업데이트 Firestore는 어레이 포함을 지원합니다.

이 문서를 가지고

    {danceName: 'Danca name 1', songName: ['Title1','Title2']}
    {danceName: 'Danca name 2', songName: ['Title3']}

이렇게 해

collection("Dances")
    .where("songName", "array-contains", "Title1")
    .get()...

@ Nelson.b.austin firestore에는 아직 해당 기능이 없으므로 평평한 구조를 갖는 것이 좋습니다.

Dances = {
    danceName: 'Dance name 1',
    songName_Title1: true,
    songName_Title2: true,
    songName_Title3: false
}

그렇게하면 다음과 같이 할 수 있습니다.

var songTitle = 'Title1';
var dances = db.collection("Dances");
var query = dances.where("songName_"+songTitle, "==", true);

이게 도움이 되길 바란다.


노래를 컬렉션이 아닌 개체로 저장하면 어떨까요? 노래를 필드로 사용하여 각 춤 : 유형 Object (컬렉션 아님)

{
  danceName: "My Dance",
  songs: {
    "aNameOfASong": true,
    "aNameOfAnotherSong": true,
  }
}

그런 다음 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);
    });

2019 업데이트

Firestore에서 컬렉션 그룹 쿼리를 출시했습니다. 위의 Gil의 답변 또는 공식 컬렉션 그룹 쿼리 문서를 참조하십시오.


이전 답변

Gil Gilbert가 말했듯이 컬렉션 그룹 쿼리 가 현재 작업중인 것처럼 보입니다 . 그동안 루트 레벨 컬렉션을 사용하고 문서 UID를 사용하여 이러한 컬렉션 사이를 연결하는 것이 더 좋습니다.

아직 모르는 사람들을 위해 Jeff Delaney는 AngularFirebase 에서 Firebase (및 Angular)로 작업하는 모든 사람을위한 놀라운 가이드와 리소스를 제공 합니다.

Firestore NoSQL 관계형 데이터 모델링 -여기서 그는 NoSQL 및 Firestore DB 구조화의 기본 사항을 분석합니다.

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 their Firestore skills to the next level


NEW UPDATE July 8, 2019:

db.collectionGroup('Songs')
  .where('songName', isEqualTo:'X')
  .get()

Query limitations

Cloud Firestore does not support the following types of queries:

  1. Queries with range filters on different fields.

  2. 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.

  3. Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
  4. 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).

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.


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;
      }
    })
);

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);
        });

참고URL : https://stackoverflow.com/questions/46573014/firestore-query-subcollections

반응형