RethinkDB GetNearest и фильтр для нескольких индексов

Можно ли запросить близлежащую точку, соответствующую одному или нескольким тегам? Это данные, которые у меня есть:

r.db("test").table("Member"):

{ "POSTALCODE":  "526494" ,
"lat":  "1.3640" , "lon":  "103.9531" ,
"memberId":  "22b99a77-5f73-4331-a5da-dcdc46a4b4e7" ,
"membertags": ["tag1" ,"tag2" , "tag3" ] ,
"point": { "$reql_type$":  "GEOMETRY" , "coordinates": [103.9531 ,1.364],"type":  "Point"}
} {
"POSTALCODE":  "525842" ,
"lat":  "1.3516" , "lon":  "103.9384" ,
"memberId":  "79844285-7781-4bd4-819e-db54f90b8c8d" ,
"membertags": ["tag2" ,"tag3" ,"tag4" ,"tag5"] ,
"point": {"$reql_type$":  "GEOMETRY" ,"coordinates": [103.9384 ,1.3516] ,"type":  "Point" }
}

Как указано в Как запустить фильтровать запрос getNearest() в RethinkDB?, я мог бы фильтровать getNearest, используя eq

var point = r.point(103.9531,1.364);  
r.db('test')
.table('Member')
.getNearest(point, {index: 'point', unit :'km'})
.filter(function(user) {
   return user('doc')('POSTALCODE').eq('525842') //1 RESULT
   //return user('doc')('membertags').eq('tag2') //EMPTY RESULT
})

но я не смог получить результат для мультииндексов (например, теги участников), как это было предложено в rethinkdb с команды filter и getNearest (вариант №1) — с помощью .filter({membertags : 'tag2'}).

Вторичный индекс был создан с использованием r.db("test").table("Member").index_create("membertags", multi=True). Я знаю, что фильтр не поддерживает вторичный индекс, но не смог найти альтернативное решение, использующее getNearest.


person totoro    schedule 11.11.2015    source источник


Ответы (1)


Если вы можете пожертвовать производительностью, чтобы использовать filter вместо индекса, мы можем сделать это:

var point = r.point(103.9531,1.364);  
r.db('test')
.table('Member')
.getNearest(point, {index: 'point', unit :'km'})
.filter(function(user) {
  return user('doc')('membertags').contains('tag2')
})

Вместо использования eq мы теперь используем contains для фильтрации результата, в котором поле membertags содержит тег.

Недостатком является то, что filter не использует индекс, поэтому производительность может быть не такой высокой.

person kureikain    schedule 11.11.2015
comment
Спасибо! - Теперь я мог расширить его, чтобы он соответствовал любому тегу, используя return user('doc')('membertags').contains(function (tag) {return tag.eq('tag1').or(tag.eq('tag2'));}) (код: pastebin.com/vTjChN0z). Но это не будет работать для условия .and (т.е. вернуть каждую запись, которая соответствует › 1 тегам). Я что-то пропустил здесь? - person totoro; 12.11.2015
comment
and всегда будет возвращать false, потому что один тег не может быть равен двум значениям одновременно. Внутри предикатной функции каждый раз элемент массива передается в предикатную функцию. Поэтому вы не можете использовать его с and. Чтобы проверить это, используйте setIntersection следующим образом: filter(function(user) { return user('doc')('membertags').setIntersection(['tag2', 'tag4']).count().eq(2) }) возвращаемые значения setIntersection появляются в обоих массивах, а затем подсчитывают размер результирующего массива. - person kureikain; 12.11.2015