Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

dbGetQuery only supports data.frame access structure now. dbGetQuery …

…supports skip,limit parameters.
  • Loading branch information...
commit 6b1702327c4b7d5151b682bf4c428ce15abb67b6 1 parent 0790f31
@tc authored
View
3  .Rbuildignore
@@ -0,0 +1,3 @@
+src
+.git
+.idea
View
6 DESCRIPTION
@@ -1,13 +1,13 @@
Package: RMongo
Type: Package
Title: MongoDB Client for R
-Version: 0.0.9
-Date: 2010-10-12
+Version: 0.0.10
+Date: 2010-10-14
Author: Tommy Chheng
Maintainer: Tommy Chheng <tommy.chheng@gmail.com>
Description: MongoDB Database interface for R. The interface is provided via Java calls to the mongo-java-driver.
License: GPL-3
LazyLoad: yes
-Depends: R(>= 2.11.0), rJava, rjson, plyr, methods
+Depends: R(>= 2.11.0), rJava, methods
SystemRequirements: Java (>= 1.6), MongoDB (>= 1.6)
URL: http://github.com/quid/RMongo
View
53 R/rmongo.R
@@ -1,9 +1,7 @@
library('rJava')
-library('plyr')
-library('rjson')
#.jinit()
-#.jaddClassPath("inst/java/r-mongo-scala-1.0-SNAPSHOT.jar"")
+#.jaddClassPath("inst/java/r-mongo-scala-1.0-SNAPSHOT.jar")
setClass("RMongo", representation(javaMongo = "jobjRef"))
@@ -12,14 +10,14 @@ mongoDbConnect <- function(dbName, host="localhost", port=27017){
rmongo
}
-flattenIdColumn <- function(rjson.list){
- lapply(rjson.list, function(doc){
- new.doc = doc
- new.doc$`_id` = doc$`_id`$`$oid`
- new.doc
- })
-}
-
+setGeneric("dbShowCollections", function(rmongo.object) standardGeneric("dbShowCollections"))
+setMethod("dbShowCollections", signature(rmongo.object="RMongo"),
+ function(rmongo.object){
+ results <- .jcall(rmongo.object@javaMongo, "[S", "dbShowCollections")
+ results
+ }
+)
+
setGeneric("dbInsertDocument", function(rmongo.object, collection, doc) standardGeneric("dbInsertDocument"))
setMethod("dbInsertDocument", signature(rmongo.object="RMongo", collection="character", doc="character"),
function(rmongo.object, collection, doc){
@@ -28,26 +26,25 @@ setMethod("dbInsertDocument", signature(rmongo.object="RMongo", collection="char
}
)
-#
-# format can be json or data.frame
-# json will return an rjson object
-# data.frame will attempt to convert to flat data frame table.
-setGeneric("dbGetQuery", function(rmongo.object, collection, query, format) standardGeneric("dbGetQuery"))
-setMethod("dbGetQuery", signature(rmongo.object="RMongo", collection="character", query="character", format="character"),
- function(rmongo.object, collection, query, format="json"){
- results <- .jcall(rmongo.object@javaMongo, "S", "dbGetQuery", collection, query)
- json.results <- fromJSON(results)
-
- if(format == "json"){
- json.results
- }else if(format == "data.frame"){
- transformed.docs <- flattenIdColumn(json.results)
- data.frame.results <- ldply(transformed.docs, data.frame)
- data.frame.results
+setGeneric("dbGetQuery", function(rmongo.object, collection, query, skip=0, limit=1000) standardGeneric("dbGetQuery"))
+setMethod("dbGetQuery", signature(rmongo.object="RMongo", collection="character", query="character", skip='numeric', limit='numeric'),
+ function(rmongo.object, collection, query, skip, limit){
+ results <- .jcall(rmongo.object@javaMongo, "S", "dbPaginateGetQuery", collection, query, skip, limit)
+ if(results == ""){
+ data.frame()
+ }else{
+ con <- textConnection(results)
+ data.frame.results <- read.csv(con)
}
}
)
+setMethod("dbGetQuery", signature(rmongo.object="RMongo", collection="character", query="character", skip='missing', limit='missing'),
+ function(rmongo.object, collection, query, skip=0, limit=1000){
+ dbGetQuery(rmongo.object, collection,query,skip,limit)
+ }
+)
+
setGeneric("dbDisconnect", function(rmongo.object) standardGeneric("dbDisconnect"))
setMethod("dbDisconnect", signature(rmongo.object="RMongo"),
function(rmongo.object){
@@ -55,5 +52,3 @@ setMethod("dbDisconnect", signature(rmongo.object="RMongo"),
}
)
-
-
View
BIN  inst/java/r-mongo-scala-1.0-SNAPSHOT.jar
Binary file not shown
View
11 man/RMongo-package.Rd
@@ -25,16 +25,17 @@ A typical workflow using RMongo:
This will query for documents which have a "foo" attribute with the value of "bar". The return value will be a list of rjson objects or a converted data.frame depending on the format parameter. NOTE: nested documents and arrays may not work properly if you specify a data.frame.
\preformatted{
output <- dbGetQuery(mongo, "test_data",
- '{"foo": "bar"}', format='json')
-
- output <- dbGetQuery(mongo, "test_data",
- '{"foo": "bar"}', format='data.frame')
-
+ '{"foo": "bar"}')
}
\item Close the connection:
\preformatted{
dbDisconnect(mongo)
}
+ \item Large result sets:
+ Set your java heap space to a large number to support loading more results into memory.
+ \preformatted{
+ options( java.parameters = "-Xmx2g" )
+ }
}
}
View
16 man/dbGetQuery-methods.Rd
@@ -2,23 +2,27 @@
\docType{methods}
\alias{dbGetQuery}
\alias{dbGetQuery-methods}
-\alias{dbGetQuery,RMongo,character,character,character-method}
+\alias{dbGetQuery,RMongo,character,character-method}
+\alias{dbGetQuery,RMongo,character,character,missing,missing-method}
+\alias{dbGetQuery,RMongo,character,character,numeric,numeric-method}
\title{Performing a MongoDB query}
\description{
-Send a json query to mongodb.
+Send a json query to mongodb.
+The output is a data.frame object and will work properly only if the mongoDB collection contains primitive data types. It may not work properly if there are any embedded documents or arrays.
}
\usage{
- dbGetQuery(rmongo.object, collection, query, format)
+ dbGetQuery(rmongo.object, collection, query, skip=0, limit=1000)
}
\arguments{
\item{rmongo.object}{The RMongo object.}
\item{collection}{The name of the collection the query is being performed upon.}
\item{query}{A JSON string query. See http://www.mongodb.org/display/DOCS/Advanced+Queries for more information on the MongoDB query language. }
- \item{format}{The format is 'json' which returns a rjson parsed list.The other option is 'data.frame' which will return a data.frame version of the resultset. WARNING: 'data.frame' will work properly only if the mongoDB collection contains primitive data types. It may not work properly if there are any embedded documents or arrays. }
+ \item{skip}{Offset the resultset. Can be used with limit to perform pagination.}
+ \item{limit}{Limits the resultset size.}
}
\seealso{
@@ -26,6 +30,6 @@ Send a json query to mongodb.
}
\examples{
mongo <- mongoDbConnect("test")
- output <- dbGetQuery(mongo, 'test_data', '{"foo": "bar"}', format='json')
- output <- dbGetQuery(mongo, 'test_data', '{"foo":"bar"}', format='data.frame')
+ output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
+ output <- dbGetQuery(mongo, 'test_data', '{"foo": "bar"}')
}
View
73 src/r-mongo-scala/src/main/scala/com/quid/RMongo.scala
@@ -1,8 +1,9 @@
package com.quid
import com.mongodb.util.JSON
-import com.mongodb.{Mongo, DBObject, DB, DBCursor}
import collection.mutable.ListBuffer
+import collection.JavaConversions._
+import com.mongodb._
/**
*
@@ -19,28 +20,59 @@ class RMongo(dbName: String, host: String, port: Int) {
def this(dbName: String) = this (dbName, "localhost", 27017)
+ def dbShowCollections():Array[String] = {
+ val names = db.getCollectionNames().map(name => name)
+
+ names.toArray
+ }
def dbInsertDocument(collectionName: String, jsonDoc: String): String = {
+ dbModificationAction(collectionName, jsonDoc, _.insert(_))
+ }
+
+ def dbRemoveQuery(collectionName: String, query: String): String = {
+ dbModificationAction(collectionName, query, _.remove(_))
+ }
+
+ def dbModificationAction(collectionName: String,
+ query: String,
+ action:(DBCollection, DBObject) => WriteResult): String = {
val dbCollection = db.getCollection(collectionName)
- val docObject = JSON.parse(jsonDoc).asInstanceOf[DBObject]
- val results = dbCollection.insert(docObject)
+ val queryObject = JSON.parse(query).asInstanceOf[DBObject]
+ val results = action(dbCollection, queryObject)
if(results.getError == null) "ok" else results.getError
}
def dbGetQuery(collectionName: String, query: String): String = {
+ dbPaginateGetQuery(collectionName, query, 0, 1000)
+ }
+
+ implicit def dbPaginateGetQuery(collectionName: String, query: String, skipNum:Double, limitNum:Double):String = dbPaginateGetQuery(collectionName, query, skipNum.toInt, limitNum.toInt)
+ def dbPaginateGetQuery(collectionName: String, query: String, skipNum:Int, limitNum:Int): String = {
val dbCollection = db.getCollection(collectionName)
val queryObject = JSON.parse(query).asInstanceOf[DBObject]
- val cursor = dbCollection.find(queryObject).iterator
+ val cursor = dbCollection.find(queryObject).skip(skipNum).limit(limitNum)
- val results = toJsonOutput(cursor)
+ val results = RMongo.toCsvOutput(cursor)
results
+ }
+
+ def close() {
+ m.close()
+ }
+
+ def main() {
+
}
+}
- def toJsonOutput(cursor: java.util.Iterator[DBObject]): String = {
+object RMongo{
+
+ def toJsonOutput(cursor:DBCursor): String = {
val results = ListBuffer[String]()
while (cursor.hasNext) {
val item = cursor.next
@@ -50,11 +82,32 @@ class RMongo(dbName: String, host: String, port: Int) {
results.mkString("[", ",", "]")
}
- def close() {
- m.close()
+ def toCsvOutput(cursor: DBCursor): String = {
+ if(cursor.hasNext == false) return ""
+
+ val results = ListBuffer[String]()
+ var first = true
+ val firstRecord:DBObject = cursor.next
+
+ val keys = firstRecord.keySet.toArray(new Array[String](firstRecord.keySet.size))
+ results.append(keys.mkString(","))
+ results.append(csvRowFromDBObject(keys, cursor.curr)) //append the first row
+
+ while (cursor.hasNext) {
+ results.append(csvRowFromDBObject(keys, cursor.next))
+ }
+
+ results.mkString("\n")
}
- def main() {
+ def csvRowFromDBObject(keys:Array[String], item:DBObject):String ={
+
+ keys.map{k =>
+ val value = item.get(k)
+ if(value != null)
+ "\"" + value.toString.replaceAll("\"", "\\\"") + "\""
+ else
+ "" }.mkString(",")
}
-}
+}
View
89 src/r-mongo-scala/src/test/scala/com/quid/MongoTest.scala
@@ -27,13 +27,21 @@ class MongoTest{
val m = new Mongo()
val db = m.getDB("test")
val collection = db.getCollection("test_data")
- val doc = """ {"foo": "bar", "size": 5} """
- val docObject = JSON.parse(doc).asInstanceOf[DBObject]
- collection.insert(docObject)
- val doc1 = """ {"foo": "n1", "size": 10} """
- val docObject1 = JSON.parse(doc1).asInstanceOf[DBObject]
- collection.insert(docObject1)
+ List(""" {"foo": "bar", "size": 5} """,
+ """ {"foo": "n1", "size": 10} """).foreach{ doc =>
+ val docObject = JSON.parse(doc).asInstanceOf[DBObject]
+ collection.insert(docObject)
+ }
+ }
+
+ @Test
+ def testDbShowCollections{
+ val rMongo = new RMongo("test")
+
+ val collectionName = "test_data"
+
+ assert(rMongo.dbShowCollections().contains(collectionName))
}
@Test
@@ -44,7 +52,6 @@ class MongoTest{
val doc = """ {"_id": "foo", "foo": "bar", "size": 5} """
val response = rMongo.dbInsertDocument("test_data", doc)
-
Assert.assertEquals("ok", response)
val duplicateResponse = rMongo.dbInsertDocument("test_data", doc)
@@ -53,15 +60,27 @@ class MongoTest{
}
@Test
+ def testDbRemoveQuery{
+ clearTestDB
+
+ val rMongo = new RMongo("test")
+ val doc = """ {"_id": "foo", "foo": "bar", "size": 5} """
+
+ val response = rMongo.dbInsertDocument("test_data", doc)
+ Assert.assertEquals("ok", response)
+
+ val removeResponse = rMongo.dbRemoveQuery("test_data", """ {"_id": "foo"} """)
+
+ Assert.assertEquals("ok", removeResponse)
+ }
+
+ @Test
def testDbGetQuery{
val rMongo = new RMongo("test")
val results = rMongo.dbGetQuery("test_data", """ {} """)
+ val record = parsedFirstRecordFrom(results)
- val jsonParsed = scala.util.parsing.json.JSON.parseFull(results)
- val records = jsonParsed.getOrElse(List()).asInstanceOf[List[Any]]
- val record = records.head.asInstanceOf[Map[String,Any]]
-
- Assert.assertEquals("bar", record.getOrElse("foo", ""))
+ Assert.assertEquals("\"bar\"", record.getOrElse("foo", ""))
}
@Test
@@ -69,17 +88,53 @@ class MongoTest{
val rMongo = new RMongo("test")
val results = rMongo.dbGetQuery("empty_collection", """ {} """)
- Assert.assertEquals("[]", results)
+ Assert.assertEquals("", results)
}
+
@Test
def testDbGetQuerySorting{
val rMongo = new RMongo("test")
val results = rMongo.dbGetQuery("test_data", """ { "$query": {}, "$orderby": { "foo": -1 } }} """)
+ val record = parsedFirstRecordFrom(results)
+
+ Assert.assertEquals("\"n1\"", record.getOrElse("foo", ""))
+ }
+
+ @Test
+ def testDbPaginateGetQuery{
+ val rMongo = new RMongo("test")
+ val page1 = rMongo.dbPaginateGetQuery("test_data", """ {} """, 0, 1)
+ val record1 = parsedFirstRecordFrom(page1)
+
+ Assert.assertEquals("\"bar\"", record1.getOrElse("foo", ""))
+
+ val page2 = rMongo.dbPaginateGetQuery("test_data", """ {} """, 1, 1)
+ val record2 = parsedFirstRecordFrom(page2)
+
+ Assert.assertEquals("\"n1\"", record2.getOrElse("foo", ""))
+ }
+
+ @Test
+ def testToCsvOutput{
+ val m = new Mongo()
+ val db = m.getDB("test")
+ val collection = db.getCollection("test_data")
+ val query = "{}"
+ val queryObject = JSON.parse(query).asInstanceOf[DBObject]
+ val cursor = collection.find(queryObject)
+
+ val results = RMongo.toCsvOutput(cursor)
+
+ println(results)
+ }
+
+ def parsedFirstRecordFrom(results: String):Map[String, Any] = {
+ val lines = results.split("\n").filter(_.size > 0)
- val jsonParsed = scala.util.parsing.json.JSON.parseFull(results)
- val records = jsonParsed.getOrElse(List()).asInstanceOf[List[Any]]
- val record = records.head.asInstanceOf[Map[String,Any]]
+ val keys = lines.head.split(",")
+ val entries = lines.drop(1)
+ val entry = entries.headOption.getOrElse("").split(",")
- Assert.assertEquals("n1", record.getOrElse("foo", ""))
+ keys.zip(entry).toMap
}
}
View
27 tests/RMongo-Ex.R
@@ -1,8 +1,6 @@
library("RUnit")
library("RMongo")
library('rJava')
-library('rjson')
-library('plyr')
test.dbInsertDocument <- function(){
mongo <- mongoDbConnect("test")
@@ -15,26 +13,25 @@ test.dbInsertDocument <- function(){
test.dbGetQuery <- function(){
mongo <- mongoDbConnect("test")
output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
- output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}', format='json')
+ output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}')
dbDisconnect(mongo)
-
- checkEquals("bar", output[[1]]$foo)
+ checkEquals("bar", as.character(output[1,]$foo))
}
-test.dbGetQueryDataFrameFormat <- function(){
- mongo <- mongoDbConnect('test')
+test.dbGetQuerySkipAndLimit <- function(){
+ mongo <- mongoDbConnect("test")
output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
- output <- dbGetQuery(mongo, 'test_data', '{"foo":"bar"}', format='data.frame')
+ output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
+ output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}', 0, 1)
dbDisconnect(mongo)
-
- checkEquals("bar", as.character(output[1,]$foo))
+ checkEquals(1, length(output[output$foo == 'bar', 1]))
}
test.dbGetQueryWithEmptyCollection <- function(){
mongo <- mongoDbConnect('test')
- output <- dbGetQuery(mongo, 'test_data', '{"EMPTY": "EMPTY"}', format='json')
+ output <- dbGetQuery(mongo, 'test_data', '{"EMPTY": "EMPTY"}')
dbDisconnect(mongo)
- checkEquals(list(), output)
+ checkEquals(data.frame(), output)
}
test.dbGetQuerySorting <- function(){
@@ -43,15 +40,15 @@ test.dbGetQuerySorting <- function(){
dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
dbInsertDocument(mongo, "test_data", '{"foo": "newbar"}')
- output <- dbGetQuery(mongo, "test_data", '{ "$query": {}, "$orderby": { "foo": -1 } }}', format='json')
+ output <- dbGetQuery(mongo, "test_data", '{ "$query": {}, "$orderby": { "foo": -1 } }}')
dbDisconnect(mongo)
- checkEquals("newbar", output[[1]]$foo)
+ checkEquals("newbar", as.character(output[1,]$foo))
}
test.dbInsertDocument()
test.dbGetQuery()
-test.dbGetQueryDataFrameFormat()
+test.dbGetQuerySkipAndLimit()
test.dbGetQueryWithEmptyCollection()
test.dbGetQuerySorting()
View
29 tests/RMongo-Ex.Rout.save
@@ -17,11 +17,7 @@ Type 'q()' to quit R.
> library("RUnit")
> library("RMongo")
Loading required package: rJava
-Loading required package: rjson
-Loading required package: plyr
> library('rJava')
-> library('rjson')
-> library('plyr')
>
> test.dbInsertDocument <- function(){
+ mongo <- mongoDbConnect("test")
@@ -34,26 +30,25 @@ Loading required package: plyr
> test.dbGetQuery <- function(){
+ mongo <- mongoDbConnect("test")
+ output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
-+ output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}', format='json')
++ output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}')
+ dbDisconnect(mongo)
-+
-+ checkEquals("bar", output[[1]]$foo)
++ checkEquals("bar", as.character(output[1,]$foo))
+ }
>
-> test.dbGetQueryDataFrameFormat <- function(){
-+ mongo <- mongoDbConnect('test')
+> test.dbGetQuerySkipAndLimit <- function(){
++ mongo <- mongoDbConnect("test")
+ output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
-+ output <- dbGetQuery(mongo, 'test_data', '{"foo":"bar"}', format='data.frame')
++ output <- dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
++ output <- dbGetQuery(mongo, "test_data", '{"foo": "bar"}', 0, 1)
+ dbDisconnect(mongo)
-+
-+ checkEquals("bar", as.character(output[1,]$foo))
++ checkEquals(1, length(output[output$foo == 'bar', 1]))
+ }
>
> test.dbGetQueryWithEmptyCollection <- function(){
+ mongo <- mongoDbConnect('test')
-+ output <- dbGetQuery(mongo, 'test_data', '{"EMPTY": "EMPTY"}', format='json')
++ output <- dbGetQuery(mongo, 'test_data', '{"EMPTY": "EMPTY"}')
+ dbDisconnect(mongo)
-+ checkEquals(list(), output)
++ checkEquals(data.frame(), output)
+ }
>
> test.dbGetQuerySorting <- function(){
@@ -62,10 +57,10 @@ Loading required package: plyr
+ dbInsertDocument(mongo, "test_data", '{"foo": "bar"}')
+ dbInsertDocument(mongo, "test_data", '{"foo": "newbar"}')
+
-+ output <- dbGetQuery(mongo, "test_data", '{ "$query": {}, "$orderby": { "foo": -1 } }}', format='json')
++ output <- dbGetQuery(mongo, "test_data", '{ "$query": {}, "$orderby": { "foo": -1 } }}')
+ dbDisconnect(mongo)
+
-+ checkEquals("newbar", output[[1]]$foo)
++ checkEquals("newbar", as.character(output[1,]$foo))
+ }
>
>
@@ -73,7 +68,7 @@ Loading required package: plyr
[1] TRUE
> test.dbGetQuery()
[1] TRUE
-> test.dbGetQueryDataFrameFormat()
+> test.dbGetQuerySkipAndLimit()
[1] TRUE
> test.dbGetQueryWithEmptyCollection()
[1] TRUE
Please sign in to comment.
Something went wrong with that request. Please try again.