Flutter에서 Parse QueryBuilder를 사용한 데이터 쿼리 최적화
Flutter에서 Parse Query 요리책
소개
우리는 이미 QueryBuilder와 함께 get를 사용하여 Back4App에서 단일 ParseObject를 검색하는 방법을 보았습니다. QueryBuilder를 사용하여 데이터를 검색하는 다른 많은 방법이 있습니다 - 여러 개체를 한 번에 검색하거나, 검색하려는 개체에 조건을 사용할 수 있으며, 그 외에도 많은 기능이 있습니다.
이 가이드에서는 QueryBuilder 클래스에 대해 깊이 파고들고 쿼리를 작성하는 데 사용할 수 있는 모든 메서드를 살펴볼 것입니다. Flutter를 사용하여 Back4App에서 쿼리를 수행하기 위해 일부 모의 데이터가 포함된 간단한 데이터베이스 클래스를 사용할 것입니다.
전제 조건
- 백4앱에 연결된 플러터 앱.
- 안드로이드 또는 iOS를 실행하는 장치(또는 가상 장치).
목표
탐색하다 QueryBuilder 클래스의 다양한 메서드.
QueryBuilder 클래스
모든 Parse 쿼리 작업은 QueryBuilder 객체 유형을 사용하며, 이는 앱 전반에 걸쳐 데이터베이스에서 특정 데이터를 검색하는 데 도움이 됩니다.
새로운 QueryBuilder, 생성하려면 원하는 ParseObject 서브클래스를 매개변수로 전달해야 하며, 이는 쿼리 결과를 포함할 것입니다.
중요한 점은 QueryBuilder는 retrieve 메서드를 호출한 후에만 해결된다는 것입니다. query, 따라서 쿼리를 설정하고 여러 수정자를 실제로 호출하기 전에 연결할 수 있습니다.
QueryBuilder 클래스에 대한 자세한 내용은 여기에서 공식 문서를 참조하십시오.
Back4App에서 JavaScript 콘솔 사용하기
Back4App 애플리케이션의 대시보드 내부에서 JavaScript 코드를 직접 실행할 수 있는 매우 유용한 API 콘솔을 찾을 수 있습니다. 이 가이드를 사용하여 Back4App에 데이터 객체를 저장할 것입니다. 앱의 주요 대시보드에서 다음으로 이동하십시오.Core->API Console->Javascript.

데이터 객체 저장하기
이 가이드에서 쿼리를 실행하려면 먼저 앱에 일부 데이터를 채워야 합니다. 유명인 이름과 다음 필드를 사용하여 소셜 미디어 프로필 클래스를 모방하는 샘플 클래스를 생성해 보겠습니다.Profile, 다음과 같은 필드를 사용합니다:
- 문자열 유형 이름:
- 날짜 유형 생일:
- 숫자 (정수) 유형 친구 수:
- 배열 (문자열 목록) 유형 좋아하는 음식:
- 배열 (숫자 목록) 유형 행운의 숫자:
- GeoPoint 유형 마지막 로그인 위치:
여기 Parse.Object 클래스 생성 코드가 있습니다. API 콘솔에서 실행해 보세요:
1 // Add Profile objects and create table
2 // Adam Sandler
3 let Profile = new Parse.Object('Profile');
4 Profile.set('name', 'Adam Sandler');
5 Profile.set('birthDay', new Date('09/09/1966'));
6 Profile.set('friendCount', 2);
7 Profile.set('favoriteFoods', ['Lobster', 'Bread']);
8 Profile.set('luckyNumbers', [2, 7]);
9 Profile.set('lastLoginLocation', new Parse.GeoPoint(37.38412167489413, -122.01268034622319));
10 await Profile.save();
11
12 // Britney Spears
13 Profile = new Parse.Object('Profile');
14 Profile.set('name', 'Britney Spears');
15 Profile.set('birthDay', new Date('12/02/1981'));
16 Profile.set('friendCount', 52);
17 Profile.set('favoriteFoods', ['Cake', 'Bread']);
18 Profile.set('luckyNumbers', [22, 7]);
19 Profile.set('lastLoginLocation', new Parse.GeoPoint(37.38412167489413, -122.01268034622319));
20 await Profile.save();
21
22 // Carson Kressley
23 Profile = new Parse.Object('Profile');
24 Profile.set('name', 'Carson Kressley');
25 Profile.set('birthDay', new Date('11/11/1969'));
26 Profile.set('friendCount', 12);
27 Profile.set('favoriteFoods', ['Fish', 'Cookies']);
28 Profile.set('luckyNumbers', [8, 2]);
29 Profile.set('lastLoginLocation', new Parse.GeoPoint(37.38412167489413, -122.01268034622319));
30 await Profile.save();
31
32 // Dan Aykroyd
33 // Creates related object Membership for this user only
34 let Membership = new Parse.Object('Membership');
35 Membership.set('name', 'Premium');
36 Membership.set('expirationDate', new Date('10/10/2030'))
37 await Membership.save();
38
39 Profile = new Parse.Object('Profile');
40 Profile.set('name', 'Dan Aykroyd');
41 Profile.set('birthDay', new Date('07/01/1952'));
42 Profile.set('friendCount', 66);
43 Profile.set('favoriteFoods', ['Jam', 'Peanut Butter']);
44 Profile.set('luckyNumbers', [22, 77]);
45 Profile.set('lastLoginLocation', new Parse.GeoPoint(37.38412167489413, -122.01268034622319));
46 Profile.set('premiumMembership', Membership);
47 await Profile.save();
48
49 // Eddie Murphy
50 Profile = new Parse.Object('Profile');
51 Profile.set('name', 'Eddie Murphy');
52 Profile.set('birthDay', new Date('04/03/1961'));
53 Profile.set('friendCount', 49);
54 Profile.set('favoriteFoods', ['Lettuce', 'Pepper']);
55 Profile.set('luckyNumbers', [6, 5]);
56 Profile.set('lastLoginLocation', new Parse.GeoPoint(-27.104919974838154, -52.61428045237739));
57 await Profile.save();
58
59 // Fergie
60 Profile = new Parse.Object('Profile');
61 Profile.set('name', 'Fergie');
62 Profile.set('birthDay', new Date('03/27/1975'));
63 Profile.set('friendCount', 55);
64 Profile.set('favoriteFoods', ['Lobster', 'Shrimp']);
65 Profile.set('luckyNumbers', [13, 7]);
66 Profile.set('lastLoginLocation', new Parse.GeoPoint(-27.104919974838154, -52.61428045237739));
67 await Profile.save();
68
69 console.log('Success!');이 코드를 실행한 후, 데이터베이스에 여섯 개의 객체가 생성된 프로필 클래스가 있어야 합니다. 새로운 클래스는 다음과 같아야 합니다:

이제 모든 쿼리 빌더 메서드의 예를 살펴보고, 각 메서드가 수행하는 작업에 대한 간단한 설명을 추가하겠습니다. 이 목록의 일부 메서드는 옵션을 추가 인수로 받을 수 있지만, 대부분의 경우 이는 마스터 키 사용과 관련이 있으며 이 가이드 내용과는 관련이 없으므로, 관련이 없는 경우 이 가능성은 생략됩니다.
쿼리 검색기
이 방법들은 쿼리를 실행하고 그 결과를 검색하는 책임이 있으며, 항상 쿼리 구현에 존재합니다.
//Retrieves the count of ParseObject results that meet the query criteria.
1 QueryBuilder<ParseObject> queryBuilder = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 var apiResponse = await queryPlayers.count();
3 if (apiResponse.success && apiResponse.result != null) {
4 int countGames = apiResponse.count;
5 }쿼리 조건자
이 방법들은 쿼리에 조건부 제약을 적용할 수 있는 가능성을 제공합니다. 이는 쿼리에서 가장 중요한 작업이라고 할 수 있습니다.
이 작업들은 결과가 검색되기 전에 모두 연결될 수 있다는 점을 기억하세요. 따라서 쿼리 요구 사항을 해결하기 위해 많은 조합을 달성할 수 있습니다.
//Requires that a key’s value does not match a value in an object returned by a different Parse.Query. Useful for multi-object querying.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.whereDoesNotMatchKeyInQuery(
3 'friendCount',
4 'friendCount',
5 QueryBuilder<ParseObject>(ParseObject('Profile'))
6 ..whereLessThan('friendCount', 50));
7 parseQuery.whereGreaterThan('friendCount', 10);
8 final apiResponse = await parseQuery.query();
9
10 if (apiResponse.success && apiResponse.results != null) {
11 for (var object in apiResponse.results as List<ParseObject>) {
12 print('${object.objectId} - Name: ${object.get<String>('name')} - friendCount: ${object.get<int>('friendCount')}');
13 }
14 }//Filters objects in which a string key value contains the provided text value. Be aware that this condition is case-sensitive.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 // This can be slow in large databases
3 parseQuery.whereContains('name', 'an');
4 final apiResponse = await parseQuery.query();
5
6 if (apiResponse.success && apiResponse.results != null) {
7 for (var object in apiResponse.results as List<ParseObject>) {
8 print('${object.objectId} - ${object.get<String>('name')}');
9 }
10 }//Filters objects in which a specific key’s value is equal to the provided value.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2
3 parseQuery.whereEqualTo('friendCount', 2);
4 final apiResponse = await parseQuery.query();
5
6 if (apiResponse.success && apiResponse.results != null) {
7 for (var o in apiResponse.results) {
8 final object = o as ParseObject;
9 print('${object.objectId} - ${object.get<String>('name')}');
10 }
11 }//Filters objects in which a specific key’s value is lesser than the provided value.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2
3 parseQuery.whereLessThan('birthDay', DateTime(1980, 08, 19));
4 final apiResponse = await parseQuery.query();
5
6 if (apiResponse.success && apiResponse.results != null) {
7 for (var object in apiResponse.results as List<ParseObject>) {
8 print('${object.objectId} - ${object.get<String>('name')}');
9 }
10 }//Requires that an object contained in the given key matches another query. Useful for multi-object querying.
1 final QueryBuilder<ParseObject> innerQuery = QueryBuilder<ParseObject>(ParseObject('Membership'));
2 innerQuery.whereGreaterThan('expirationDate', DateTime.now());
3
4 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
5
6 parseQuery.whereValueExists('premiumMembership', true);
7 parseQuery.whereMatchesQuery('premiumMembership', innerQuery);
8
9 final apiResponse = await parseQuery.query();
10
11 if (apiResponse.success && apiResponse.results != null) {
12 for (var object in apiResponse.results as List<ParseObject>) {
13 print('${object.objectId} - Name: ${object.get<String>('name')}');
14 }
15 }쿼리 정렬
대부분의 쿼리에서 필수적이며, Parse에서 쉽게 정렬할 수 있으며 두 개 이상의 정렬 제약 조건 간에 체인할 수 있습니다.
//Sort the results in descending order, this can be chained without overwriting previous orderings. Multiple keys can be used to solve ordering ties.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.orderByDescending('name');
3 final apiResponse = await parseQuery.query();
4
5 if (apiResponse.success && apiResponse.results != null) {
6 for (var object in apiResponse.results as List<ParseObject>) {
7 print('${object.objectId} - ${object.get<String>('name')}');
8 }
9 }필드 선택
이 메서드는 쿼리 결과에 포함될 수 있는 필드 값을 결정합니다.
//Return all fields in the returned objects except the ones specified.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.excludeKeys(['name']);
3 final apiResponse = await parseQuery.query();
4
5 if (apiResponse.success && apiResponse.results != null) {
6 for (var object in apiResponse.results as List<ParseObject>) {
7 //Name = null
8 print('${object.objectId} - Name: ${object.get<String>('name')} - Birthday: ${object.get<DateTime>('birthDay')}');
9 }
10 }지오포인트 쿼리
이것은 GeoPoint 쿼리에 특정한 방법입니다.
//Return all fields in the returned objects except the ones specified.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.whereNear(
3 'lastLoginLocation',
4 ParseGeoPoint(latitude: 37.38412167489413, longitude: -122.01268034622319)
5 );
6
7 final apiResponse = await parseQuery.query();
8
9 if (apiResponse.success && apiResponse.results != null) {
10 for (var object in apiResponse.results as List<ParseObject>) {
11 print('${object.objectId} - Name: ${object.get<String>('name')} - GeoPoint: ${object.get<ParseGeoPoint>('lastLoginLocation').toJson()}');
12 }
13 }1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.whereWithinKilometers(
3 'lastLoginLocation',
4 ParseGeoPoint(latitude: 37.38412167489413, longitude: -122.01268034622319),
5 100
6 );
7
8 final apiResponse = await parseQuery.query();
9
10 if (apiResponse.success && apiResponse.results != null) {
11 for (var object in apiResponse.results as List<ParseObject>) {
12 print('${object.objectId} - Name: ${object.get<String>('name')} - GeoPoint: ${object.get<ParseGeoPoint>('lastLoginLocation').toJson()}');
13 }
14 }페이지 매김
이 메서드는 많은 결과를 검색하는 쿼리에 유용한 페이지 매김 유틸리티와 관련이 있습니다.
1 final QueryBuilder<ParseObject> parseQuery = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 parseQuery.setLimit(2);
3 final apiResponse = await parseQuery.query();
4
5 if (apiResponse.success && apiResponse.results != null) {
6 for (var object in apiResponse.results as List<ParseObject>) {
7 print('${object.objectId} - Name: ${object.get<String>('name')}');
8 }
9 }복합 쿼리
이 메서드는 복합 쿼리를 생성하여 여러 ParseQuery 인스턴스를 결합하여 더 복잡한 결과를 얻을 수 있습니다.
//Compose a compound query that is the OR of the passed queries.
1 final QueryBuilder<ParseObject> query1 = QueryBuilder<ParseObject>(ParseObject('Profile'));
2 query1.whereGreaterThan('friendCount', 10);
3
4 final QueryBuilder<ParseObject> query2 = QueryBuilder<ParseObject>(ParseObject('Profile'));
5 query2.whereLessThan('friendCount', 50);
6
7 QueryBuilder<ParseObject> mainQuery = QueryBuilder.or(
8 ParseObject("Profile"),
9 [query1, query2],
10 );
11
12 final apiResponse = await mainQuery.query();
13
14 if (apiResponse.success && apiResponse.results != null) {
15 for (var object in apiResponse.results as List<ParseObject>) {
16 print('${object.objectId} - Name: ${object.get<String>('name')}');
17 }
18 }결론
이 가이드의 끝에서, 당신은 Parse에서 모든 데이터 쿼리 메서드를 수행하는 방법을 배웠습니다. 다음 가이드에서는 Flutter에서 복잡한 Parse 쿼리에 대해 배울 것입니다.