Как проверить тип поля перед проверкой значения в rethinkdb?

У меня есть несколько таблиц в rethinkdb с очень разными наборами данных. В основном потому, что со временем из простых строковых свойств были созданы сложные объекты, которые были более выразительными.

Когда я запускаю запрос, я удостоверяюсь, что все поля существуют, с помощью hasFields - функция. Но что, если я хочу запустить запрос RegExp для моего свойства Message, которое может иметь тип строки или объекта. Конечно, если это объект, меня не волнует строка, но вместо того, чтобы игнорировать ее, rethinkdb выдает ошибку:

Необработанный отказ RqlRuntimeError: ожидается тип STRING, но найден OBJECT в...

Могу ли я каким-то образом использовать typeOf, чтобы сначала определить тип перед выполнением запроса?

Или что было бы хорошим способом сделать это?


person peter    schedule 10.05.2015    source источник


Ответы (2)


Ваш вопрос не ясен для меня на 100%, поэтому я собираюсь переформулировать проблему, чтобы убедиться, что мое решение имеет смысл.

Проблема

Получить все документы, в которых свойство message имеет тип object или свойство message является строкой и соответствует определенному регулярному выражению (используя match).

Решение

В основном вам нужен оператор if. Для этого вы можете использовать r.branch для "разветвления" ваших условий в зависимости от этих вещей.

Вот очень длинный, но наглядный пример того, как это сделать:

Допустим, у вас есть эти документы, и вам нужны все документы, в которых свойство message является объектом или строкой, содержащей подстроку «строка». Документы выглядят так:

{
  "id":  "a1a17705-e7b0-4c84-b9d5-8a51f4599eeb" ,
  "message":  "invalid"
}, {
  "id":  "efa3e26f-2083-4066-93ac-227697476f75" ,
  "message":  "this is a string"
}, {
 "id":  "80f55c96-1960-4c38-9810-a76aef60d678" ,
  "not_messages": "hello"
}, {
  "id":  "d59d4e9b-f1dd-4d23-a3ef-f984c2361226" ,
  "message": {
    "exists": true ,
    "text":  "this is a string"
  }
}

Для этого вы можете использовать следующий запрос:

r.table('messages')
  .hasFields('message') // only get document with the `message` property
  .filter(function (row) { 
    return r.branch( // Check if it's an object
      row('message').typeOf().eq('OBJECT'), // return true if it's an object
      true,
      r.branch( // Check if it's a string
        row('message').typeOf().eq('STRING'),
        r.branch( // Only return true if the `message` property ...
          row('message').match('string'), // has the substring `string`
          true,
          false // return `false` if it's a string but doesn't match our regex
        ),
        false // return `false` if it's neither a string or an object
      )
    )
  })

Опять же, этот запрос длинный и мог бы быть написан более элегантно, но он объясняет использование branch очень четко.

Более короткий способ написания этого запроса таков:

r.table('messages')
  .hasFields('message')
  .filter(function (row) {
    return 
      row('message').typeOf().eq('OBJECT')
        .or(
          row('message').typeOf().eq('STRING').and(row('message').match('string'))
        )
  })

В основном это использует and и or вместо branch.

person Jorge Silva    schedule 10.05.2015
comment
на самом деле это не ответ на мой вопрос, но он очень проясняет, как использовать функцию typeOf, это все, что мне нужно, большое спасибо - person peter; 10.05.2015
comment
Тогда я не очень понял ваш вопрос. Можно уточнить, в чем был вопрос? Просто из любопытства. - person Jorge Silva; 10.05.2015
comment
да, я хотел просто запустить match, если элемент является строкой, и игнорировать объект, поэтому я могу просто пропустить первую часть вашего условия, но было также приятно увидеть более сложные запросы в качестве примера, спасибо - person peter; 10.05.2015
comment
Превосходно. Имеет смысл. - person Jorge Silva; 10.05.2015

Этот запрос вернет вам все регистры в табличном сообщении, которые имеют поле message и поле String. Ваше здоровье.

r.db('test').table('message').hasFields('message')
.filter(function (row) { 
    return row('message').typeOf().eq('STRING')
})
person Thomas Modeneis    schedule 07.09.2016