基於Firebase中的多個where子句進行查詢


Answers

使用Firebase的新查詢API ,您可能會嘗試嘗試以下操作:

// !!! THIS WILL NOT WORK !!!
ref
  .orderBy('genre')
  .startAt('comedy').endAt('comedy')
  .orderBy('lead')                  // !!! THIS LINE WILL RAISE AN ERROR !!!
  .startAt('Jack Nicholson').endAt('Jack Nicholson')
  .on('value', function(snapshot) { 
      console.log(snapshot.val()); 
  });

但正如Firebase的@RobDiMarco在評論中所說:

多個orderBy()調用將引發錯誤

所以我上面的代碼不起作用

我知道三種方法可行。

1.在服務器上過濾最多,在客戶端上執行其餘部分

可以做的是在服務器上執行一個orderBy().startAt()./endAt() ,將剩下的數據下拉並在客戶端用JavaScript代碼過濾。

ref
  .orderBy('genre')
  .equalTo('comedy')
  .on('child_added', function(snapshot) { 
      var movie = snapshot.val();
      if (movie.lead == 'Jack Nicholson') {
          console.log(movie);
      }
  });

2.添加一個屬性,將您想要過濾的值組合在一起

如果這還不夠好,你應該考慮修改/擴展你的數據以允許你的用例。 例如:您可以將流派+主角引入您剛用於此過濾器的單個屬性。

"movie1": {
    "genre": "comedy",
    "name": "As good as it gets",
    "lead": "Jack Nicholson",
    "genre_lead": "comedy_Jack Nicholson"
},...

你基本上是用這種方式構建自己的多列索引,並可以通過以下方式進行查詢:

ref
  .orderBy('genre_lead')
  .equalTo('comedy_Jack Nicholson')
  .on('child_added', function(snapshot) { 
      var movie = snapshot.val();
      console.log(movie);
  });

David East編寫了一個名為QueryBase庫,幫助生成這些屬性

你甚至可以進行相對/範圍查詢,假設你想允許按類別和年份查詢電影。 你會使用這個數據結構:

"movie1": {
    "genre": "comedy",
    "name": "As good as it gets",
    "lead": "Jack Nicholson",
    "genre_year": "comedy_1997"
},...

然後用以下方式查詢90年代的喜劇:

ref
  .orderBy('genre_year')
  .startAt('comedy_1990')
  .endAt('comedy_2000')
  .on('child_added', function(snapshot) { 
      var movie = snapshot.val();
      console.log(movie);
  });

如果您需要過濾一年以上,請確保按降序添加其他日期部分,例如"comedy_1997-12-25" 。 這樣,Firebase對字符串值的字典排序將與時間順序相同。

這種屬性值的組合可以使用兩個以上的值,但只能對組合屬性中的最後一個值執行範圍過濾。

FirebaseGeoFire庫實現了一個非常特殊的變體。 該庫將位置的經度和緯度組合成所謂的Geohash ,然後可用於在Firebase上進行實時範圍查詢。

3.以編程方式創建自定義索引

另一種選擇是在添加新的Query API之前完成我們所做的全部工作:在不同的節點中創建索引:

  "movies"
      // the same structure you have today
  "by_genre"
      "comedy"
          "by_lead"
              "Jack Nicholson"
                  "movie1"
              "Jim Carrey"
                  "movie3"
      "Horror"
          "by_lead"
              "Jack Nicholson"
                  "movie2"

可能有更多的方法。 例如,此答案突出顯示了一種替代樹形自定義索引: https://stackoverflow.com/a/34105063 : https://stackoverflow.com/a/34105063

Question
{
"movies": {
    "movie1": {
        "genre": "comedy",
        "name": "As good as it gets",
        "lead": "Jack Nicholson"
    },
    "movie2": {
        "genre": "Horror",
        "name": "The Shining",
        "lead": "Jack Nicholson"
    },
    "movie3": {
        "genre": "comedy",
        "name": "The Mask",
        "lead": "Jim Carrey"
    }
  }  
 }

我是Firebase新手。 如何從以上數據中檢索genre = 'comedy' AND lead = 'Jack Nicholson'

我有什麼選擇?




var ref = new Firebase('https://your.firebaseio.com/');

Query query = ref.orderByChild('genre').equalTo('comedy');
query.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot movieSnapshot : dataSnapshot.getChildren()) {
            Movie movie = dataSnapshot.getValue(Movie.class);
            if (movie.getLead().equals('Jack Nicholson')) {
                console.log(movieSnapshot.getKey());
            }
        }
    }

    @Override
    public void onCancelled(FirebaseError firebaseError) {

    }
});



我已經編寫了一個個人圖書館,允許您通過多個值進行訂購,並在服務器上完成所有訂購。

滿足查詢庫!

Querybase接收Firebase數據庫引用以及您想要索引的字段數組。 當您創建新記錄時,它將自動處理允許多次查詢的密鑰的生成。 需要注意的是,它只支持直接等價(不小於或大於)。

const databaseRef = firebase.database().ref().child('people');
const querybaseRef = querybase.ref(databaseRef, ['name', 'age', 'location']);

// Automatically handles composite keys
querybaseRef.push({ 
  name: 'David',
  age: 27,
  location: 'SF'
});

// Find records by multiple fields
// returns a Firebase Database ref
const queriedDbRef = querybaseRef
 .where({
   name: 'David',
   age: 27
 });

// Listen for realtime updates
queriedDbRef.on('value', snap => console.log(snap));