Firebase의 다중 where 절을 기준으로 쿼리
{
"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"
}
}
}
저는 파이어베이스 신입입니다.AND 위의 데이터에서 결과를 검색하려면 어떻게 해야 합니까?
어떤 선택지가 있습니까?
Firebase의 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()
시 합니다.
그래서 위의 제 코드는 작동하지 않을 것입니다.
저는 효과적인 세 가지 접근법을 알고 있습니다.
서버에서 가장 많이 필터링하고 나머지는 클라이언트에서 수행합니다.
당신이 할 수 있는 것은 하나를 실행하는 것입니다.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);
}
});
필터링할 값을 결합한 속성 추가
이 방법으로 충분하지 않다면 사용 사례를 허용하도록 데이터를 수정/확장하는 것을 고려해야 합니다.예를 들어, 이 필터에 사용하는 단일 속성에 장르+리드를 넣을 수 있습니다.
"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가 문자열 값에 대해 수행하는 사전 순서는 시간순 순서와 동일합니다.
속성의 이러한 값 조합은 세 개 이상의 값에서 작동할 수 있지만 복합 속성의 마지막 값에 대해서만 범위 필터를 수행할 수 있습니다.
이것의 매우 특별한 변형은 Firebase용 GeoFire 라이브러리에 의해 구현됩니다.이 라이브러리는 위치의 위도와 경도를 이른바 지오해시로 결합하여 Firebase에서 실시간 범위 쿼리를 수행하는 데 사용할 수 있습니다.
프로그래밍 방식으로 사용자 정의 인덱스 생성
또 다른 대안은 이 새로운 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
이러한 옵션 중 어느 것도 사용할 수 없지만 Firebase에 데이터를 저장하려는 경우 Cloud Firestore 데이터베이스를 사용하는 것도 고려할 수 있습니다.
Cloud Firestore는 단일 쿼리에서 여러 동일 필터를 처리할 수 있지만 범위 필터는 하나만 처리할 수 있습니다.후드 아래에서는 기본적으로 동일한 쿼리 모델을 사용하지만, 이는 복합 속성을 자동으로 생성하는 것과 같습니다.복합 쿼리에 대한 자세한 내용은 Firestore 설명서를 참조하십시오.
여러 값으로 주문할 수 있는 개인 라이브러리를 작성했고, 서버에서 모든 주문을 수행할 수 있습니다.
쿼리 기반 충족!
쿼리베이스는 Firebase Database Reference 및 인덱싱할 필드 배열을 가져옵니다.새 레코드를 만들면 여러 개의 쿼리를 허용하는 키 생성이 자동으로 처리됩니다.주의할 점은 직선 동등성만 지원한다는 것입니다(이상 또는 그 이상).
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));
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) {
}
});
프랭크의 답변은 좋지만 최근에 파이어스토어에서 AND 쿼리를 더 쉽게 할 수 있도록 소개했습니다.
다음을 생성할 수 있습니다.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"
]
}
}
}
클라우드 Firestore의 경우
https://firebase.google.com/docs/firestore/query-data/queries#compound_queries
복합 쿼리 여러 등호 연산자(== 또는 배열 지정) 메서드를 연결하여 보다 구체적인 쿼리(논리 AND)를 만들 수 있습니다.연산자를 .<, <=, >, and !=
.
citiesRef.where('state', '==', 'CO').where('name', '==', 'Denver');
citiesRef.where('state', '==', 'CA').where('population', '<', 1000000);
범위를 수행할 수 있습니다.(<, <=, >, >=)
않은 것이 같나같지않음거▁or음않입니다.(!=)
단일 필드에 대해서만 비교할 수 있으며 복합 쿼리에 최대 하나의 array-interval 또는 array-interval-any 절을 포함할 수 있습니다.
Firebase에서는 여러 조건으로 쿼리할 수 없습니다.하지만, 저는 이것을 위한 방법을 찾았습니다.
우리는 데이터베이스에서 초기 필터링된 데이터를 다운로드하여 배열 목록에 저장해야 합니다.
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()));
}
Firebase 실시간 데이터베이스의 데이터는 _InternalLinkedHashMap<dynamic, dynamic>과 같습니다.이를 지도로 변환하여 매우 쉽게 조회할 수도 있습니다.
예를 들어, 저는 채팅 앱이 있고 실시간 데이터베이스를 사용하여 사용자의 UID와 사용자가 온라인 상태인지 여부에 관계없이 부울 값을 저장합니다.아래 사진과 같이.
이제 클래스 Realtime Database와 정적 메서드 getAllUsersOnineStatus()가 있습니다.
static getOnilineUsersUID() {
var dbRef = FirebaseDatabase.instance;
DatabaseReference reference = dbRef.reference().child("Online");
reference.once().then((value) {
Map<String, bool> map = Map<String, bool>.from(value.value);
List users = [];
map.forEach((key, value) {
if (value) {
users.add(key);
}
});
print(users);
});
}
[NORADTGaQSZb]가 인쇄됩니다.IEszidCujw1Aym2]
저는 설레임이 처음입니다. 더 많은 것을 알고 있다면 답변을 업데이트해주세요.
ref.orderByChild("lead").startAt("Jack Nicholson").endAt("Jack Nicholson").listner....
이것은 효과가 있을 거예요.
언급URL : https://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase
'IT' 카테고리의 다른 글
ARM 템플릿에서 단일 따옴표를 이스케이프하는 방법 (0) | 2023.06.07 |
---|---|
루비 배열에서 평균을 만들려면 어떻게 해야 합니까? (0) | 2023.06.07 |
여러 CSV 파일을 단일 xls 워크북 Python 3에 결합 (0) | 2023.06.07 |
길이가 큰 VARCHAR2 열 정의의 영향 (0) | 2023.06.07 |
피벗 테이블 목록의 오래된 항목 (0) | 2023.06.07 |