rmongodb: используя $ или в запросе
Я изо всех сил пытаюсь создать запрос, используя $ или внутри R и rmongodb. То, что я хотел бы подражать, это из cmdline mongo:
db.people.find( { $or : [ {"person.cell": { $exists : true } }, {"person.home": { $exists : true } } ] })
Я хотел бы получить записи, где либо person.cell не является нулевым, либо person.home не является нулевым. Я могу запросить каждый по отдельности, но не могу получить данные обратно, когда я создаю буфер в rmongodb с помощью $ или, код R с использованием rmongodb выглядит следующим образом:
l <- list("$exists"="true")
buf <- mongo.bson.buffer.create()
mongo.bson.buffer.start.array(buf, "$or")
mongo.bson.buffer.append.list(buf, "person.cell", l)
mongo.bson.buffer.append.list(buf, "person.home", l)
mongo.bson.buffer.finish.object(buf)
b <- mongo.bson.from.buffer(buf)
mongo.find(mongo, "work.people", b)
Это не возвращает ни записей, ни ошибок, просто пустой набор. Как я уже упоминал, я могу найти либо в person.cell, либо в person.home и получить результаты, но не тогда, когда я пытаюсь сделать $ или (в rmongodb), чтобы я получал записи с помощью person.cell или person.home.,
Я также попробовал это:
buf <- mongo.bson.buffer.create()
mongo.bson.buffer.start.array(buf, "$or")
mongo.bson.buffer.start.object(buf, "person.cell")
mongo.bson.buffer.append(buf, "$exists", "true")
mongo.bson.buffer.finish.object(buf)
mongo.bson.buffer.start.object(buf, "person.home")
mongo.bson.buffer.append(buf, "$exists", "true")
mongo.bson.buffer.finish.object(buf)
mongo.bson.buffer.finish.object(buf)
b <- mongo.bson.from.buffer(buf)
mongo.find(mongo, "work.people", b)
Но я получаю тот же самый пустой результат набора (и "b" выглядит одинаково, когда я его просматриваю). Я застрял на этом.
4 ответа
bson <- mongo.bson.from.JSON('{ "$or" : [ {"person.cell": { "$exists" : true } }, {"person.home": { "$exists" : true } } ] }')
mongo.find(mongo, "work.people", bson)
Ваш способ создания массива Монго Бсон неверен. Вам не хватает частей
mongo.bson.buffer.start.object(buf, "0")
...
mongo.bson.buffer.finish.object(buf)
mongo.bson.buffer.start.object(buf, "1")
...
mongo.bson.buffer.finish.object(buf)
Для рабочего примера, пожалуйста, проверьте последний комментарий: https://github.com/mongosoup/rmongodb/issues/17
Я надеюсь, что это работает на данный момент.
Во всех командах.to.list /.from.list / .append.list есть ошибка. Я работаю над более простым решением!
Чтобы избежать необходимости составлять последовательность операторов mongo.bson.buffer, я написал пакет ( rmongodbHelper), который преобразует JSON или list() в объект BSON, который затем можно использовать с rmongodb.
Сначала давайте настроим среду:
library(rmongodb)
# install rmongodbHelper package from GitHub
library(devtools)
devtools::install_github("joyofdata/rmongodbHelper")
library(rmongodbHelper)
# the MongoDB instance
ns <- "dbx.collx"
M <- mongo.create()
mongo.is.connected(M)
mongo.remove(M, ns, json_to_bson("{}"))
# inserting a number of dummy objects
# JSON keys currently are expected to be wrapped in double quotes!
objs <- c(
'{"_id":-1}',
'{"_id":-2, "person":{}}',
'{"_id":-3, "person":{"x":0}}',
'{"_id":1, "person":{"cell":0}}',
'{"_id":2, "person":{"home":0}}',
'{"_id":3, "person":{"cell":0,"home":0}}'
)
for(obj in objs) {
mongo.insert(M, ns, json_to_bson(obj))
}
Давайте посмотрим через оболочку MongoDB, были ли они успешно вставлены:
> use dbx
switched to db dbx
> db.collx.find().pretty()
{ "_id" : -1 }
{ "_id" : -2, "person" : { } }
{ "_id" : -3, "person" : { "x" : 0 } }
{ "_id" : 1, "person" : { "cell" : 0 } }
{ "_id" : 2, "person" : { "home" : 0 } }
{ "_id" : 3, "person" : { "cell" : 0, "home" : 0 } }
Теперь давайте поищем документы с запросом:
# searching for those objects
# JSON keys currently are expected to be wrapped in double quotes!
json_qry <-
'{
"$or" : [
{"person.cell": { "$exists" : true } },
{"person.home": { "$exists" : true } }
]
}'
cur <- mongo.find(M, "dbx.collx", json_to_bson(json_qry))
while(mongo.cursor.next(cur)) {
print(mongo.cursor.value(cur))
}
И вот что мы получаем в итоге:
_id : 1 1.000000
person : 3
cell : 1 0.000000
_id : 1 2.000000
person : 3
home : 1 0.000000
_id : 1 3.000000
person : 3
cell : 1 0.000000
home : 1 0.000000
Я нашел этот запрос легче спорить в RMongo:
mongo <- mongoDbConnect(dbName="work", host="localhost",port='27017')
result <- dbGetQuery(mongo, "people","
{ '$or': [
{'person.cell':{'$exists':true}},
{'person.home':{'$exists':true}}
]}"
)
Результат будет data.frame
,