Linguagem de query

O Realm JavaScript SDK suporta queries com base em uma linguagem inspirada no NSPredicate.

O método Collection.filtered() é usado para fazer uma query em um Realm:

let contacts = realm.objects('Contact');
let friendsPage2 = contacts.filtered('type == "friend" AND name BEGINSWITH "B"');

É possível filtrar por objetos vinculados ou filhos com um caminho chave.

Exemplo:

let johnsChildren = realm.Object('Contact').filtered('father.name == "John"');

As strings de query podem usar placeholders numerados ($0, $1, ...). Os parâmetros seguintes contêm os valores. Os placeholders nomeados ainda não são compatíveis.

Exemplo:

let merlots = wines.filtered('variety == $0 && vintage <= $1', 'Merlot', maxYear);

Operadores condicionais

Você pode utilizar a comparação de igualdade em todos os tipos de propriedade: == e !=

Além disso, o seguinte pode ser usado em tipos numéricos: <, <=, >, >=

Exemplo:

let oldContacts = realm.objects('Contact').filtered('age > 2');

Observe que, para propriedades booleanas, você deve testar true ou false.

Exemplo:

let women = realm.objects('Contact').filtered('isMale == false');

Além disso, você pode usar o operador IN para fazer uma query a uma propriedade.

Exemplo:

let favoriteNames = realm.objects('Contact').filtered("name IN {'John', 'Mary'}");

Operadores de strings

Para propriedade de string, as query de prefixo, sufixo e substring são suportadas usando os operadores BEGINSWITH, ENDSWITH, CONTAINS e LIKE .

Para qualquer operação de string, você pode anexar [c] ao operador para torná-lo insensível a maiúsculas e minúsculas.

Exemplo:

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

Você pode fazer a correspondência curinga simples com LIKE , que suporta o uso ? para corresponder a um único caractere e * para corresponder a zero ou vários caracteres.

Exemplo:

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

composição

Use parênteses () e os operadores &&/AND e ||/OR para compor query. Você pode negar um predicado com !/NOT.

Carimbos de data e hora

Normalmente, as queries podem ser escritas com substituição de variável para que a sintaxe das datas seja atendida pelo Realm. No entanto, às vezes, é melhor compor uma query totalmente baseada em strings. Nesse caso, a sintaxe segue os formatos YYYY-MM-DD@HH:MM:SS:N ou YYYY-MM-DDTHH:MM:SS:N , onde o sufixo :N especifica nanossegundos, mas pode ser omitido (padrão é 0). Se preferir, um formato programático também oferece suporte a TSS:NS , que é um T literal seguido de segundos desde a Era UNIX e o modificador de nanossegundos. Em ambos os formatos, os nanossegundos negativos são considerados sintaxe inválida. Os timestamps não são cotados como strings. Devido às limitações da plataforma, o uso da primeira sintaxe não é suportado para datas anteriores à Era UNIX no Windows e anteriores a 1901 em outras plataformas.

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

Limitando o tamanho do conjunto de resultados

Para limitar o número de objetos em um conjunto de resultados, você pode usar LIMIT.

Exemplo:

realm.objects('Person').filtered('age >= 20 LIMIT(2)')  // at most two objects which fulfil the condition

query sobre collection

Quando objeto contêm listas, você pode query usando os operadores de collection ANY, ALL e NONE.

Exemplo:

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

Você pode fazer query em agregados sobre propriedade nas listas usando os operadores agregados .@count, .@avg, .@min, .@max e .@sum.

Exemplo:

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

As subqueries usando o operador SUBQUERY permitem filtrar as listas em vários parâmetros ao consultá-las.

Exemplo:

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

query sobre listas de primitivos

A sintaxe de query para uma lista de valores primitivos é principalmente a mesma que fazer query de uma lista de objetos por meio de links ou listas. No entanto, existem algumas pequenas diferenças. Para ilustrar, vamos construir um reconhecimento de data center de filmes, onde cada filme tem uma classificação por estrelas anônima e uma lista de marcações de strings.

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

Assim como nas listas de objetos, podemos usar agregados: .@count, .@avg, .@min, .@max, .@sum. collection operators (ANY, ALL, NONE) também estão disponíveis. Se nada for especificado, ANY estará implícito. Vejamos alguns exemplos de query do reconhecimento de data center de filmes:

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

Em comparação com listas de objetos, há uma operação exclusiva em listas de primitivos que é .length. Este operador comparará o comprimento de cada elemento individual do tipo string ou binário. Isso ocorre porque o operador .@size já é usado para especificar o número de elementos na lista.

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

Queries de backlink

Como os backlink são um conceito indiretamente, vamos considerar um exemplo em execução com os seguintes modelos:

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
  }
};

Os links são propriedade que são um Tipo de objeto de Realm, por exemplo Car.owner é um link direto. Você pode consultar uma cadeia de elos direto seguindo os nomes das propriedades do link (consulte a consulta 1 no exemplo abaixo). A query é auto-descritiva. E se quisermos saber quais pessoas possuem um determinado tipo de carro? Podemos encontrar isso usando backlink. Backlink é um termo usado para descrever o seguir de um relacionamento para trás. Esse relacionamento inverso sempre existe para cada propriedade do link e não é necessário nomeá-la no modelo. Podemos usar o backlink nomeado (query 2 no exemplo abaixo) da mesma forma que fizemos com um relacionamento direto. No entanto, você também pode fazer query de backlinks sem um nome, descrevendo completamente o relacionamento direto usando a sintaxe @links.ClassName.PropertyName (query 3 no exemplo abaixo). Independentemente de serem nomeados ou não, os backlink podem ser tratados como uma collection. Isso significa que você pode usar todos os collection operators como de costume (query 4 a 7 no exemplo abaixo). Além dos operadores de collection, há sintaxe especial para permitir a query da contagem de todos os relacionamento de backlink (query 8 no exemplo abaixo), que é diferente da query da contagem de backlink em um relacionamento específico (query 5 no exemplo abaixo), a menos que há apenas um link de entrada no total. Embora não haja diferença funcional entre usar backlinks nomeados e não nomeados, a legibilidade da sintaxe da query é afetada, de modo que normalmente é preferido nomear o backlink com uma propriedade linkingObject quando possível.

Exemplos:

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