代码之家  ›  专栏  ›  技术社区  ›  AngularM

firebase实时数据库-通过多个筛选器筛选列表[重复]

  •  0
  • AngularM  · 技术社区  · 6 年前
    {
    "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"
        }
      }  
     }
    

    我是一个新手。如何从上面的数据中检索结果 在哪里? genre = 'comedy' lead = 'Jack Nicholson' ?

    我有什么选择?

    0 回复  |  直到 7 年前
        1
  •  211
  •   Frank van Puffelen    6 年前

    使用 Firebase's Query 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。添加合并要筛选的值的属性

    如果这还不够好,您应该考虑修改/扩展您的数据以允许您的用例。例如:您可以将genre+lead填充到一个单独的属性中,只用于此筛选器。

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

    大卫·伊斯特写了一篇 library called QueryBase that helps with generating such properties .

    您甚至可以执行相对/范围查询,假设您希望允许按类别和年份查询电影。您将使用以下数据结构:

    "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对字符串值所做的词典顺序将与时间顺序相同。

    一个属性中的值组合可以处理两个以上的值,但只能对复合属性中的最后一个值进行范围筛选。

    它的一个非常特殊的变体是由 GeoFire library for Firebase . 这个库将一个位置的经纬度组合成一个所谓的 Geohash ,然后可用于在firebase上执行实时范围查询。

    三。以编程方式创建自定义索引

    另一种选择是在添加这个新的查询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

        2
  •  41
  •   David East    8 年前

    我已经编写了一个个人库,允许您通过多个值进行排序,所有的排序都在服务器上完成。

    Meet Querybase!

    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));
    
        3
  •  2
  •   Mehmed Andrew Lam    7 年前
    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) {
    
        }
    });
    
        4
  •  0
  •   jaleel    6 年前
    ref.orderByChild("lead").startAt("Jack Nicholson").endAt("Jack Nicholson").listner....
    

    这会奏效的。