Використовуючи API запиту Firebase , ви можете спробувати це:
// !!! 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());
});
Але як в коментарях говорить @RobDiMarco з Firebase:
кілька 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);
});
Девід Іст написав бібліотеку під назвою 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 виконує за рядковими значеннями, буде таким самим, як і хронологічне впорядкування.
Це поєднання значень у властивості може працювати з більш ніж двома значеннями, але ви можете зробити лише фільтр діапазону за останнім значенням у складеному властивості.
Дуже особливий варіант цього реалізується бібліотекою GeoFire для Firebase . Ця бібліотека поєднує широту і довготу місця в так званому Geohash , який потім може бути використаний для запитів в режимі реального часу на Firebase.
3. створити спеціальний індекс програмно
Ще одна альтернатива - зробити те, що ми зробили, перш ніж додавати цей новий 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
orderBy()
дзвінки призведуть до помилки, оскільки клієнти наразі дають несподівані результати. Цілком можливо, що він випадково працював у вашому тесті, але він не створений для того, щоб це працював загалом (хоча ми хотіли б його додати!).