rmongodb: using $or in query

前提是你 提交于 2019-11-28 10:10:08

问题


I'm struggling to create a query using $or within R and rmongodb. What I'd like to emulate is this from cmdline mongo:

db.people.find( { $or : [ {"person.cell": { $exists : true } }, {"person.home": { $exists : true } } ] })

I'd like to pull records where either person.cell is not null, or person.home is not null. I can query each individually, but cannot get data back when I create the buffer in rmongodb with the $or, the R code using rmongodb looks like this:

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)

That returns no records, no error, just an empty set. As I mentioned, I can do a find on either person.cell or person.home and get results, but not when I try to do an $or (in rmongodb) so that I pull records with either person.cell or person.home.

I've also tried this:

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)

But I get the same empty set result (and "b" looks the same when I view it). I'm stuck on this one.


回答1:


your way of creating an mongo bson array is wrong. You are missing the parts

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)

For a working example please check the latest comment on: https://github.com/mongosoup/rmongodb/issues/17

I hope this works for now.

There is a bug in all the .to.list / .from.list / .append.list commands. I am working on an easier solution!




回答2:


bson <- mongo.bson.from.JSON('{ "$or" : [ {"person.cell": { "$exists" : true } }, {"person.home": { "$exists" : true } } ] }')
mongo.find(mongo, "work.people", bson)



回答3:


To avoid having to compose the sequence of mongo.bson.buffer-statements I wrote a package (rmongodbHelper) that will translate a JSON or a list() to a BSON object which can then be used with rmongodb.

First let's setup the environment:

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

Let's see via MongoDB shell if they were successfully inserted:

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

Now let's search for documents with a query:

# 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))
}

And this is what we get in the end:

_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



回答4:


I found this query easier to wrangle in RMongo:

mongo <- mongoDbConnect(dbName="work", host="localhost",port='27017')
result <- dbGetQuery(mongo, "people","
    { '$or': [
        {'person.cell':{'$exists':true}},
        {'person.home':{'$exists':true}}
    ]}"
)

Result will be a data.frame.



来源:https://stackoverflow.com/questions/12067020/rmongodb-using-or-in-query

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!