クエリ言語

Realm JavaScript SDK は、 NPredateに触発された言語に基づくクエリをサポートします。

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

string演算子

string プロパティの場合、プレフィックス、サフィックス、サブストリング クエリは、 BEGINSWITHENDSWITHCONTAINS 、およびLIKE演算子を使用することでサポートされています。

どの string 操作でも、演算子に[c]を追加して、大文字と小文字を区別しないようにできます。

例:

let peopleWhoseNameContainsA = realm.objects('Contact').filtered('name CONTAINS[c] "a"');
let Johns = realm.objects('Contact').filtered('name ==[c] "john"');

LIKEでは単純なワイルドカード一致を実行できます。これは、 ?を使用して 1 文字の文字を一致させ、 *を使用して 0 文字または複数の文字を一致させるのをサポートしています。

例:

// Matches "John" and "Johnny"
let Johns = realm.objects('Contact').filtered('name LIKE "John*"');

構成

括弧()&& / ANDおよび|| / OR演算子を使用してクエリを作成します。 ! / NOTを使用して述語を否定できます。

タイムスタンプ

通常のクエリは変数置換を使用して記述できるため、日付の構文は Realm によって管理されます。 ただし、完全に string ベースのクエリを作成する方が適している場合があります。 その場合、構文はYYYY-MM-DD@HH:MM:SS:NまたはYYYY-MM-DDTHH:MM:SS:Nの形式に従います。ここでは、 :Nサフィックスは ナノ秒を指定しますが、省略することもできます(デフォルトは 0)。 希望する場合、プログラムによる形式ではTSS:NSもサポートされています。これはリテラルのTに続くエポックからの秒数と ナノ秒 修飾子です。 どちらの形式でも、負のナノ秒は無効な構文と見なされます。 タイムスタンプは string のように引用符で囲まれることはありません。 プラットフォームの制限のため、最初の構文を使用することは、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

コレクションに対するクエリ

オブジェクトにリストが含まれている場合は、コレクション演算子ANYALLNONEを使用してそれらをクエリできます。

例:

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

プリミティブのリストに対するクエリ

プリミティブ値のリストのクエリ構文は、リンクまたはリストを介してオブジェクト リストをクエリする方法とほとんど同じです。 ただし、いくつかの小さな違いがあります。 説明のために、各映画に匿名のスター評価と string タグのリストがある映画データベースを構築します。

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 。 コレクション演算子( ANYALLNONE )も使用できます。 指定されていない場合は、 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である一意の操作が 1 つあります。 この演算子は、string またはバイナリの各要素の長さを比較します。 これは、 .@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
  }
};

リンクはオブジェクトタイプであるプロパティです。たとえば、 Car.ownerはフォワード リンクです。 リンク プロパティ名に従うと、フォワード リンク チェーンを介してクエリを実行できます(以下の例のクエリ 1 を参照してください)。 クエリは自己記述型です。 特定のタイプの自動車を所有しているユーザーを調べたい場合 バックリンクを使用して、これを見つけることができます。 バックリンクとは、関係を逆方向に追跡するのを説明するために使用される用語です。 この下位関係はすべてのリンク プロパティに常に存在し、モデルで名前を付ける必要はありません。 名前付きバックリンク(以下の例ではクエリ 2)を、フォワード関係の場合と同様に使用できます。 ただし、 @links.ClassName.PropertyName構文を使用してフォワード関係を完全に説明することで、名前なしでバックリンクをクエリすることもできます(以下の例ではクエリ 3)。 名前が付けられているかどうかに関係なく、バックリンクはコレクションのように扱われます。 つまり、すべてのコレクション演算子を通常どおり使用できます(以下の例では、クエリ 4 ~ 7)。 コレクション演算子に加えて、すべてのバックリンク関係の数をクエリできるようにする特別な構文があります(以下の例ではクエリ 8)。これは、特定の関係でのバックリンク数のクエリ(以下の例ではクエリ 5)とは異なります。受信リンクは合計で 1 つだけです。 名前付きバックリンクと名前のないバックリンクの使用に機能的な違いはありませんが、クエリ構文の読みやすさに影響するため、可能な場合はバックリンクに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')