Realm JavaScript SDK는 NSPredicate 에서 영감을 받은 언어를 기반으로 쿼리를 지원합니다.
Collection.filtered()
메서드는 Realm을 쿼리하는 데 사용됩니다.
let contacts = realm.objects('Contact');
let friendsPage2 = contacts.filtered('type == "friend" AND name BEGINSWITH "B"');
키 경로가 있는 연결된 객체 또는 하위 객체를 기준으로 필터링할 수 있습니다.
예시:
let johnsChildren = realm.Object('Contact').filtered('father.name == "John"');
쿼리 문자열은 번호가 매겨진 ($0
, $1
, ...) 자리 표시자를 사용할 수 있습니다. 후속 매개변수에는 값이 포함됩니다. 명명된 자리 표시자는 아직 지원 되지 않습니다 .
예시:
let merlots = wines.filtered('variety == $0 && vintage <= $1', 'Merlot', maxYear);
조건 연산자
모든 속성 유형에 동등성 비교를 사용할 수 있습니다: ==
및 !=
또한 숫자 유형에 <
, <=
, >
, >=
을 사용할 수 있습니다.
예시:
let oldContacts = realm.objects('Contact').filtered('age > 2');
부울 속성의 경우 true
또는 false
에 대해 테스트해야 합니다.
예시:
let women = realm.objects('Contact').filtered('isMale == false');
또한 IN
연산자를 사용하여 속성을 쿼리할 수 있습니다.
예시:
let favoriteNames = realm.objects('Contact').filtered("name IN {'John', 'Mary'}");
문자열 연산자
문자열 속성의 경우 BEGINSWITH
, ENDSWITH
, CONTAINS
및 LIKE
연산자를 사용하여 접두사, 접미사 및 하위 문자열 쿼리가 지원됩니다.
모든 문자열 연산의 경우 연산자에 [c]
을 추가하여 대소문자를 구분하지 않도록 할 수 있습니다.
예시:
let peopleWhoseNameContainsA = realm.objects('Contact').filtered('name CONTAINS[c] "a"');
let Johns = realm.objects('Contact').filtered('name ==[c] "john"');
LIKE
을(를) 사용하여 단일 문자와 일치시키고 *
?
(를) 사용하여 0개 또는 여러 문자와 일치하도록 지원하는 을(를) 사용하여 간단한 와일드카드 일치를 수행할 수 있습니다.
예시:
// Matches "John" and "Johnny"
let Johns = realm.objects('Contact').filtered('name LIKE "John*"');
구성
괄호 ()
와 &&
/AND
, ||
/OR
연산자를 사용하여 쿼리를 작성합니다. !
/NOT
을 사용하여 조건자를 무효화할 수 있습니다.
타임스탬프
일반적으로 쿼리는 변수 대체를 사용하여 작성되어 Realm에서 날짜 구문을 처리하도록 할 수 있습니다. 그러나 때로는 완전히 문자열 기반의 쿼리를 작성하는 것이 더 나을 때도 있습니다. 이 경우 구문은 YYYY-MM-DD@HH:MM:SS:N
또는 YYYY-MM-DDTHH:MM:SS:N
형식을 따르며, 여기서 :N
접미사는 나노초를 지정하지만 생략할 수 있습니다(기본값은 0). 원하는 경우 프로그래밍 형식에서도 리터럴 T
뒤에 유닉스 시간 이후 초(초)와 나노초 수정자가 오는 TSS:NS
을 지원합니다. 두 형식 모두에서 음수나노초는 잘못된 구문으로 간주됩니다. 타임스탬프는 문자열처럼 인용되지 않습니다. 플랫폼 제한으로 인해 Windows에서는 유닉스 시간 이전, 다른 플랫폼에서는 1901년 이전의 날짜에는 첫 번째 구문을 사용하는 것이 지원되지 않습니다.
realm.objects('Person').filtered('birthday == 2017-12-04@0:0:0') // readable date omitting nanoseconds (assumes 0)
realm.objects('Person').filtered('birthday == 2015-7-2@14:23:17:233') // readable date including nanoseconds
realm.objects('Person').filtered('birthday == T1435846997:233') // equivalent to above
realm.objects('Person').filtered('birthday == 1970-1-1@0:0:0:0') // epoch is the default non-null Timestamp value
결과 집합의 크기 제한
결과 세트의 객체 수를 제한하려면 LIMIT
을 사용할 수 있습니다.
예시:
realm.objects('Person').filtered('age >= 20 LIMIT(2)') // at most two objects which fulfil the condition
collection에 대한 쿼리
객체에 목록이 포함된 경우 collection 연산자 ANY
, ALL
및 NONE
를 사용하여 쿼리할 수 있습니다.
예시:
// Find contacts with one or more teenage friends
let teens = realm.objects('Contact').filtered('ANY friends.age < 14');
// Find contacts where all friends are older than 21
let adults = realm.objects('Contact').filtered('ALL friends.age > 21');
애그리게이션 연산자 .@count
, .@avg
, .@min
, .@max
및 .@sum
를 사용하여 목록의 속성에 대한 애그리게이션을 쿼리할 수 있습니다.
예시:
// Find contacts without friends
let lonely = realm.objects('Contact').filtered('friends.@count == 0');
// Find contacts where the average age of their friends is above 40
let adults = realm.objects('Contact').filtered('friends.@avg.age > 40');
SUBQUERY
연산자를 사용하는 하위 쿼리를 사용하면 쿼리하는 동안 여러 매개변수에 걸쳐 목록을 필터링할 수 있습니다.
예시:
// Find contacts with friends above 21 in SF
let teens = realm.objects('Contact').filtered('SUBQUERY(friends, $friend, $friend.age > 21 AND $friend.city = "SF").@count > 0');
기본 요소 목록에 대한 쿼리
기본 값 목록에 대한 쿼리 구문은 링크나 목록을 통해 객체 목록을 쿼리하는 것과 대부분 동일합니다. 그러나 몇 가지 작은 차이점이 있습니다. 예를 들어, 각 영화에 익명의 별점과 문자열 태그 목록이 있는 영화 데이터베이스를 구성해 보겠습니다.
const MovieSchema = {
name: 'Movie',
properties: {
name: 'string',
ratings: 'int[]',
tags: 'string[]',
}
};
let realm = new Realm({schema: [MovieSchema]});
realm.write(() => {
let m0 = realm.create('Movie', {
name: 'The Matrix',
ratings: [5, 5, 3, 4, 5, 1, 5],
tags: ['science fiction', 'artificial reality'],
});
let m1 = realm.create('Movie', {
name: 'Inception',
ratings: [3, 5, 3, 4, 5, 5],
tags: ['dream', 'science fiction', 'thriller'],
})
});
객체 목록과 마찬가지로 .@count
, .@avg
, .@min
, .@max
, .@sum
애그리게이션을 사용할 수 있습니다. collection 연산자(ANY
, ALL
, NONE
)도 사용할 수 있습니다. 아무것도 지정하지 않으면 ANY
이(가) 암시됩니다. 영화 데이터베이스의 몇 가지 예시 쿼리를 살펴보겠습니다.
// Find movies which have a "science fiction" tag, [c] marks a case insensitive string comparison
realm.objects('Movie').filtered('tags =[c] "science fiction"')
// Find movies which have any tag that begins with the text "science" (string operators: LIKE, CONTAINS, BEGINSWITH, ENDSWITH are also available)
realm.objects('Movie').filtered('tags BEGINSWITH[c] "science"')
// Find movies that have only single word tags by filtering out any words with a space
realm.objects('Movie').filtered('NONE tags CONTAINS " "')
// Find movies that have an average rating of more than 4 stars
realm.objects('Movie').filtered('ratings.@avg >= 4')
// Find movies that do not have any one star ratings
realm.objects('Movie').filtered('ALL ratings > 1')
// Find movies that have a tag that is also the title (multi-property comparison of the same types is allowed)
realm.objects('Movie').filtered('ANY tags = name')
객체 목록과 비교하여 원시 목록에는 .length
이라는 고유한 작업이 한 가지 있습니다. 이 연산자는 문자열 또는 바이너리 유형의 각 개별 요소의 길이를 비교합니다. 이는 .@size
연산자가 목록의 요소 수를 지정하는 데 이미 사용되었기 때문입니다.
// Find movies that have over 100 tags
realm.objects('Movie').filtered('tags.@size > 100')
// Find movies that have a tag (ANY is implied) that is over 100 characters in length
realm.objects('Movie').filtered('tags.length > 100')
역링크 쿼리
역링크는 간접적인 개념이므로 다음 모델을 사용하여 실행 중인 예제를 살펴보겠습니다.
const CarSchema = {
name: 'Car',
properties: {
make: 'string',
model: 'string',
price: 'double',
owner: 'Person',
}
};
const PersonSchema = {
name: 'Person',
properties: {
name: 'string',
cars: { type: 'linkingObjects', objectType: 'Car', property: 'owner' }, // backlinks of Car.owner, this property is optional
}
};
링크는 Realm 객체 유형인 속성이며, 예를 들어 Car.owner
은 정방향 링크입니다. 링크 속성 이름을 따라 정방향 링크 체인을 쿼리할 수 있습니다(아래 예의 쿼리 1 참조). 쿼리는 자체 설명이 가능합니다. 어떤 사람들이 특정 유형의 자동차를 소유하고 있는지 알고 싶다면 어떻게 해야 하나요? 역링크를 사용하여 이를 찾을 수 있습니다. 역링크는 관계를 거꾸로 따라가는 것을 설명하는 데 사용되는 용어입니다. 이 역방향 관계는 항상 모든 링크 속성에 존재하며 모델에서 이름을 지정할 필요는 없습니다. 정방향 관계에서와 마찬가지로 명명된 역링크(아래 예에서는 쿼리 2)를 사용할 수 있습니다. 그러나 @links.ClassName.PropertyName
구문을 사용하여 정방향 관계를 완전히 설명함으로써 이름 없이 역링크를 쿼리할 수도 있습니다(아래 예에서 쿼리 3). 역링크의 이름 여부에 관계없이 역링크는 collection처럼 취급될 수 있습니다. 즉, 모든 collection 연산자를 평소대로 사용할 수 있습니다(아래 예에서는 쿼리 4~7). 컬렉션 연산자 외에도 특정 관계에 대한 역링크 수를 쿼리하는 것(아래 예에서 쿼리 5)과 다른 모든 역링크 관계의 수를 쿼리할 수 있는 특수 구문(아래 예에서 쿼리 8)이 있습니다. 수신 링크는 총 하나뿐입니다. 명명된 역링크를 사용하는 것과 명명되지 않은 역링크를 사용하는 것 사이에 기능적 차이는 없지만 쿼리 구문의 가독성에 영향을 미치므로 일반적으로 가능하면 linkingObject
속성을 사용하여 역링크의 이름을 지정하는 것이 좋습니다.
예시:
// Query 1) Find all cars which have an owner named 'bob' (case insensitive equality)
realm.objects('Car').filtered('owner.name ==[c] "bob"')
// Query 2) Find which people own a certain type of car by using a named backlink (any is implied)
realm.objects('Person').filtered('cars.make ==[c] "honda"')
// Query 3) Find which people own a certain type of car by using the unnamed backlink syntax
realm.objects('Person').filtered('@links.Car.owner.make ==[c] "honda"')
// Query 4) collection aggregate operator example using the unnamed backlink syntax
realm.objects('Person').filtered('@links.Car.owner.@avg.price > 30000')
// Query 5) Find people who have 3 cars using the named backlink syntax
realm.objects('Person').filtered('cars.@count == 3')
// Query 6) Find people who own a Honda which has a price > 30000 using the unnamed backlink syntax with SUBQUERY
realm.objects('Person').filtered('SUBQUERY(@links.Car.owner, $x, $x.make ==[c] "honda" && $x.price > 30000).@count > 1')
// Query 7) Find people who own only a specific type of car
realm.objects('Person').filtered('ALL @links.Car.owner.make ==[c] "honda"')
// Query 8) Find people with no incoming links (across all linked properties)
realm.objects('Person').filtered('@links.@count == 0')