While MySQL turns me on, I'm trying to get to know my first NoSQL DBMS, and that turned out to be MongoDB . I connect to it through rmongodb .
The more I play with rmongodb , the more questions / problems arise when running advanced queries.
First, I present some examples of data before I go into detail about the various types of queries that I cannot correctly specify.
Data examples
The example is taken from the MongoDB website and is a bit simplified.
pkg <- "rmongodb" if (!require(pkg, character.only=TRUE)) { install.packages(pkg) require(pkg, character.only=TRUE) } # Connect to DB db <- "test" ns <- "posts" mongo <- mongo.create(db=db) # Insert document to collection 'test.users' b <- mongo.bson.from.list(list( "_id"="alex", name=list(first="Alex", last="Benisson"), karma=1.0, age=30, test=c("a", "b") )) mongo.insert(mongo, "test.users", b) # Insert document to collection 'test.posts' b <- mongo.bson.from.list(list( "_id"="abcd", when=mongo.timestamp.create(strptime("2011-09-19 02:00:00", "%Y-%m-%d %H:%M:%s"), increment=1), author="alex", title="Some title", text="Some text.", tags=c("tag.1", "tag.2"), votes=5, voters=c("jane", "joe", "spencer", "phyllis", "li"), comments=list( list( who="jane", when=mongo.timestamp.create(strptime("2011-09-19 04:00:00", "%Y-%m-%d %H:%M:%s"), increment=1), comment="Some comment." ), list( who="meghan", when=mongo.timestamp.create(strptime("2011-09-20 13:00:00", "%Y-%m-%d %H:%M:%s"), increment=1), comment="Some comment." ) ) ) ) b mongo.insert(mongo, "test.posts", b)
Two questions related to inserting JSON / BSON objects:
- Test.posts document, voters field: is it correct to use
c() in this case? - Test.posts document,
comments field: what is the right way to indicate this, c() or list() ?
Top level queries: they work with cure
Top level queries work very well:
# Get all posts by 'alex' (only titles) res <- mongo.find(mongo, "test.posts", query=list(author="alex"), fields=list(title=1L)) out <- NULL while (mongo.cursor.next(res)) out <- c(out, list(mongo.bson.to.list(mongo.cursor.value(res)))) > out [[1]] _id title "abcd" "No Free Lunch"
Question 1: Basic sub-level queries
How can I run simple “level-level queries” (as opposed to top-level queries) that should fall into the arbitrarily deep JSON / BSON sublevels of the MongoDB object style? These sub level queries use MongoDB dot notation , and I can't figure out how to map this to a valid rmongodb request
In simple MongoDB syntax, something like
> db.posts.find( { comments.who : "meghan" } )
will work. But I can not figure out how to do this with rmongodb functions
Here is what I have tried so far
# Get all comments by 'meghan' from 'test.posts'
Question 2: Queries with $ Operators
These works
Request 1
buf <- mongo.bson.buffer.create() mongo.bson.buffer.start.object(buf, "age") mongo.bson.buffer.append(buf, "$lte", 30) mongo.bson.buffer.finish.object(buf) criteria <- mongo.bson.from.buffer(buf) criteria > mongo.find.one(mongo, "test.users", query=criteria) _id : 2 alex name : 3 first : 2 Alex last : 2 Benisson karma : 1 1.000000 age : 1 30.000000 test : 4 0 : 2 a 1 : 2 b
Request 2
buf <- mongo.bson.buffer.create() mongo.bson.buffer.start.object(buf, "test") mongo.bson.buffer.append(buf, "$in", c("a", "z")) mongo.bson.buffer.finish.object(buf) criteria <- mongo.bson.from.buffer(buf) criteria mongo.find.one(mongo, "test.users", query=criteria)
However, note that atomic dialing will result in a NULL return value
mongo.bson.buffer.append(buf, "$in", "a") # Instead of 'mongo.bson.buffer.append(buf, "$in", c("a", "z"))'
An attempt of the same with sub level queries is again lost
buf <- mongo.bson.buffer.create() mongo.bson.buffer.start.object(buf, "name") mongo.bson.buffer.start.object(buf, "first") mongo.bson.buffer.append(buf, "$in", c("Alex", "Horst")) mongo.bson.buffer.finish.object(buf) mongo.bson.buffer.finish.object(buf) criteria <- mongo.bson.from.buffer(buf) criteria <- mongo.bson.from.buffer(buf) > criteria name : 3 first : 3 $in : 4 0 : 2 Alex 1 : 2 Horst > mongo.find.one(mongo, "test.users", query=criteria) NULL