ফায়ারবেসে একাধিক ক্লজের ভিত্তিতে ক্যোয়ারী


244
{
"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' ওপরের তথ্য থেকে কীভাবে ফলাফল পুনরুদ্ধার করতে পারি ?

আমার কাছে কী বিকল্প আছে?

উত্তর:


238

ফায়ারবেসের ক্যোয়ারী এপিআই ব্যবহার করে , আপনি এটি চেষ্টা করতে প্ররোচিত হতে পারেন:

// !!! 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()); 
  });

তবে ফায়ারবেস থেকে @ রবডিমার্কো মন্তব্যগুলিতে বলেছেন:

একাধিক orderBy()কল একটি ত্রুটি নিক্ষেপ করবে

সুতরাং উপরের আমার কোডটি কাজ করবে না

আমি তিনটি পদ্ধতির জানি যা কাজ করবে।

1. সার্ভারে সর্বাধিক ফিল্টার করুন, ক্লায়েন্টের উপর বাকীটি করুন

আপনি যা করতে পারেন তা হ'ল orderBy().startAt()./endAt()সার্ভারে একটি কার্যকর করা, অবশিষ্ট ডেটাটি টানুন এবং এটি আপনার ক্লায়েন্টের জাভাস্ক্রিপ্ট কোডে ফিল্টার করুন।

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

২. এমন একটি বৈশিষ্ট্য যুক্ত করুন যা আপনি যে মানগুলিতে ফিল্টার করতে চান তার সাথে মিলিত হয়

যদি এটি যথেষ্ট ভাল না হয় তবে আপনার ব্যবহারের ক্ষেত্রে আপনার অনুমতি দেওয়ার জন্য আপনার ডেটা সংশোধন / প্রসারিত করার কথা বিবেচনা করা উচিত। উদাহরণস্বরূপ: আপনি জেনার + লিড স্টাফ করতে পারেন এমন একক সম্পত্তি যা আপনি এই ফিল্টারটির জন্য ব্যবহার করেন property

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

ডেভিড ইস্ট কোয়েরিবেস নামে একটি গ্রন্থাগার লিখেছেন যা এই জাতীয় বৈশিষ্ট্য তৈরিতে সহায়তা করে

এমনকি আপনি আপেক্ষিক / ব্যাপ্তি অনুসন্ধান করতে পারেন, আসুন আমরা বলি যে আপনি বিভাগ এবং বছর অনুসারে মুভিগুলির অনুসন্ধানের অনুমতি দিতে চান। আপনি এই ডেটা কাঠামোটি ব্যবহার করবেন:

"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"। ফায়ারবেস স্ট্রিংয়ের মানগুলিতে যেভাবে ডিকোসোগ্রাফিকাল ক্রম হয় তা কালানুক্রমিক ক্রম হিসাবে একই হবে।

কোনও সম্পত্তির মানগুলির সংমিশ্রণটি দুটিরও বেশি মানের সাথে কাজ করতে পারে তবে আপনি কেবল সম্মিলিত সম্পত্তিতে সর্বশেষ মানটিতে একটি পরিসীমা ফিল্টার করতে পারেন।

এর একটি খুব বিশেষ রূপটি ফায়ারবেসের জন্য জিওফায়ার লাইব্রেরি দ্বারা প্রয়োগ করা হয়েছে । এই গ্রন্থাগারটি একটি তথাকথিত দ্রাঘিমাংশ এবং দ্রাঘিমাংশকে তথাকথিত জিওহ্যাশের সাথে সংযুক্ত করে , যা ফায়ারবেসে রিয়েলটাইম রেঞ্জ অনুসন্ধান করতে ব্যবহৃত হতে পারে।

৩. প্রোগ্রাম হিসাবে কাস্টম সূচক তৈরি করুন

তবুও আরেকটি বিকল্প হ'ল এই নতুন কোয়েরি এপিআই যুক্ত হওয়ার আগে আমরা যা করেছি তা করা: একটি ভিন্ন নোডে একটি সূচক তৈরি করুন:

  "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


3
এটি পরের সপ্তাহে আনুষ্ঠানিকভাবে প্রকাশিত হলে, একাধিক orderBy()কল একটি ত্রুটি ছুঁড়ে দেবে, কারণ ক্লায়েন্টরা বর্তমানে অপ্রত্যাশিত ফলাফল দেয়। এটা সম্ভব যে এটি কাকতালীয়ভাবে আপনার পরীক্ষায় কাজ করেছে, তবে এটি সাধারণভাবে কাজ করার জন্য নির্মিত হয়নি (যদিও আমরা এটি যুক্ত করতে চাই!)।
রব ডিমার্কো

18
এটি এখনও ফায়ারবেস ভি 3 এর সাথে প্রাসঙ্গিক? এটি করার আরও ভাল উপায় নেই?
পিয়ের

27
আমরা .equalTo('comedy')পরিবর্তে ব্যবহার করতে পারি না কেন .startAt('comedy').endAt('comedy')?
জে কার্লোসআর

41
এটি 2018, এর কোনও সহজ সমাধান নেই? এটি রিলেশনাল ডাটাবেসে 101 এর ক্যোয়ারের মতো। এবং এসকিউএল # 8 সম্পর্কে কথা বলার সাথে ডেভিডের ভিডিওতে সমস্ত মন্তব্য দেওয়া হয়েছে, আমি আশা করি Google এখনই এটিকে সংশোধন করবে। আমি কিছু আপডেট মিস করেছি?
সাপ

10
@ স্নেক ফেব্রুয়ারী 2019 এবং সমস্যাটি এখনও স্থির হয়নি .... গুগল খুব ধীর।
সুপারটেকনোবফ

48

আমি একটি ব্যক্তিগত পাঠাগার লিখেছি যা আপনাকে সার্ভারে সমস্ত ক্রম দিয়ে একাধিক মান দ্বারা অর্ডার করতে দেয়।

কোয়েরিবেসে দেখা!

কোয়েরিবেস একটি ফায়ারবেস ডাটাবেস রেফারেন্স এবং আপনি সূচী করতে চান এমন ক্ষেত্রগুলির একটি বিন্যাস গ্রহণ করে। আপনি যখন নতুন রেকর্ড তৈরি করবেন এটি স্বয়ংক্রিয়ভাবে কীগুলির জেনারেশন পরিচালনা করবে যা একাধিক অনুসন্ধানের জন্য অনুমতি দেয়। সতর্কবাণীটি হ'ল এটি কেবল সরল সমতা সমর্থন করে (এর চেয়ে কম বা বেশি নয়)।

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

আপনার লাইব্রেরির জন্য কোনও টাইপস্ক্রিপ্ট সংজ্ঞা উপলব্ধ?
লেবি ফুলার

1
এটি টিএস-এ লেখা! তাই কেবল আমদানি করুন :)
ডেভিড পূর্ব

7
আপনি কি জানেন যে তারা কেন ডেটাবেসকে এতটা বিধিনিষেধযুক্ত করেছিল?
সিড করুন

1
আইওএস সুইফট / অ্যান্ড্রয়েড সংস্করণটি করার কোনও বিকল্প
mding5692

1
ডেভিড, এর সাথে কোনও অ্যান্ড্রয়েড / জাভা সমতা?
সাপ

3
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) {

    }
});

3
DataSnaphot অবজেক্টে কোনও getLead () পদ্ধতি নেই।
পরাগ কদম

3
তিনি এটিকে মুভি অবজেক্টে রূপান্তর করেছেন এবং ধরে নিয়েছেন যে একটি গেটলিড () মিথো আছে।
কিম জি ফ্যাম

1
অনেক ধন্যবাদ। এটি এমন আরও কাজ করছে যেখানে ক্লজ
নুওয়ান উইথানেজ

1

ফ্র্যাঙ্কের উত্তরটি ভাল তবে ফায়ারস্টোর array-containsসম্প্রতি চালু করেছে যা করাকে আরও সহজ করে তোলে এবং কোয়েরি করে।

আপনি filtersফিল্টার যোগ করার জন্য আপনি একটি ক্ষেত্র তৈরি করতে পারেন । আপনি প্রয়োজন হিসাবে অনেক মান যোগ করতে পারেন। উদাহরণস্বরূপ কমেডি এবং জ্যাক নিকোলসনের মাধ্যমে ফিল্টার করার জন্য আপনি মানটি যুক্ত করতে পারেন তবে comedy_Jack Nicholsonআপনি যদি কমেডি এবং 2014 এর মাধ্যমেও চান তবে আপনি comedy_2014আরও ক্ষেত্র তৈরি না করে মান যুক্ত করতে পারেন ।

{
"movies": {
    "movie1": {
        "genre": "comedy",
        "name": "As good as it gets",
        "lead": "Jack Nicholson",
        "year": 2014,
        "filters": [
          "comedy_Jack Nicholson",
          "comedy_2014"
        ]
    }
  }  
}

1

ফায়ারবেস একাধিক শর্ত নিয়ে জিজ্ঞাসা করার অনুমতি দেয় না। তবে আমি এর জন্য একটি উপায় খুঁজে পেয়েছি:

আমাদের ডাটাবেস থেকে প্রাথমিক ফিল্টার করা ডেটা ডাউনলোড করতে হবে এবং এটি অ্যারে তালিকায় সংরক্ষণ করতে হবে।

                Query query = databaseReference.orderByChild("genre").equalTo("comedy");
                databaseReference.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                        ArrayList<Movie> movies = new ArrayList<>();
                        for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                            String lead = dataSnapshot1.child("lead").getValue(String.class);
                            String genre = dataSnapshot1.child("genre").getValue(String.class);

                            movie = new Movie(lead, genre);

                            movies.add(movie);

                        }

                        filterResults(movies, "Jack Nicholson");

                        }

                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });

আমরা যখন ডাটাবেস থেকে প্রাথমিক ফিল্টার করা ডেটা প্রাপ্ত করি, আমাদের ব্যাকএন্ডে আরও ফিল্টার করা দরকার।

public void filterResults(final List<Movie> list,  final String genre) {
        List<Movie> movies = new ArrayList<>();
        movies = list.stream().filter(o -> o.getLead().equals(genre)).collect(Collectors.toList());
        System.out.println(movies);

        employees.forEach(movie -> System.out.println(movie.getFirstName()));
    }

-1
ref.orderByChild("lead").startAt("Jack Nicholson").endAt("Jack Nicholson").listner....

এটি কাজ করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.