Запрос составного мультииндекса в RethinkDB

Я пытаюсь эффективно получить данные в следующем формате:

{
  "datetime": "1453845345493",
  "someIds": ["id2000-4", "id1000-34", "id2000-43", "id250-34"]
}

В частности, я хочу «найти все записи, которые произошли с заданного времени, и из них вернуть все, у которых есть один или несколько из списка идентификаторов».

До сих пор я следовал методу, показанному здесь для создания составного мультииндекса с использованием следующего:

r.db("dbName").table("tableName")
  .indexCreate(
    "idDatetime", 
    function(each) {
      return each("someIds").map(function(id){
        return [each("datetime"), id]
      })
    }
    ,{multi: true})

Это успешно строит индекс на основе значений, которые выглядят как ["1453845345493", "id2000-4"]

Но теперь мне кажется, что я слишком углубился и на самом деле не знаю, как сделать запрос, который использует этот индекс для достижения указанной выше цели. Как вы составляете этот запрос?


person Brideau    schedule 27.01.2016    source источник


Ответы (2)


Я думаю (возможно, я ошибаюсь), в основном у нас есть два типа поиска по индексу:

  • точное совпадение: get, getAll
  • совпадение диапазона: between

Итак, в вашем случае мы явно не можем использовать getAll, потому что вы хотите find all records that have happened since a given time, and of those, return any that have one or more of a list of Id.

Это оставляет нам только between. Итак, давайте найдем способ смоделировать это.

Я предлагаю изменить поле datetime на числовое вместо строки. Я думаю, вы храните эпоху.

Мы создадим индекс, как вы:

r.table('t11').indexCreate('idDatetime', function(doc) {
  return doc('someIds').map(function(id){
        return [doc("datetime"), id]
  })
}, {multi: true})

Затем мы запрашиваем его примерно так:

r.table('t11')
 .between([1453845345493, "id1000-34"], [r.maxval, "id1000-34"], {index: 'idDatetime'})

Чтобы найти весь документ с той эпохи и содержит id1000-34. Вы можете найти эпоху вчерашнего дня, используя функцию даты и времени JavaScript или RethinkDB.


ОБНОВИТЬ:

Хотя это не идеально, мы можем смоделировать любой идентификатор с помощью sth следующим образом:

r.expr(["id1000-34", "id1000-4"])
  .concatMap(function(needle) {
    return r.table('t11')
     .between([1453845345499, needle], [r.maxval, needle], {index: 'idDatetime'})
  })
  .distinct()
person kureikain    schedule 27.01.2016
comment
Этот подход хорошо работает, если я хочу фильтровать по времени, а затем искать один тег, но не в том случае, если я хочу фильтровать по времени, а затем искать несколько тегов. Пример, который я упомянул в другом комментарии, заключался в том, чтобы найти все сообщения со вчерашнего дня, которые содержат «id2000-1», «id2000-3» или «id2000-5». Я более подробно изучил структуру индексов в RethinkDB и не уверен, что в настоящее время это возможно... - person Brideau; 28.01.2016
comment
Да, ты прав. В настоящее время это невозможно. Тем не менее, мы можем сделать некоторые обходные пути. Я обновил ответ некоторыми ifno - person kureikain; 28.01.2016

Если нет, обязательно ознакомьтесь с этой страницей, посвященной мультииндексам. в наших документах.

Пример использования данных, которые вы показали, будет выглядеть следующим образом:

r.table("tableName").getAll("id2000-4", {index: "idDatetime"}).run(conn, callback)

Это должно дать вам все документы в этой таблице, которые имеют id2000-4 в этом массиве.

Дайте мне знать, если это сработает для вас!

person dalanmiller    schedule 27.01.2016
comment
Трудность, с которой я сталкиваюсь, заключается в том, что я хочу отфильтровать две вещи: диапазон дат, а затем посмотреть, имеет ли объект один из многих идентификаторов. Например, найдите все сообщения со вчерашнего дня, которые содержат «id2000-1», «id2000-3» или «id2000-5». - person Brideau; 27.01.2016