Mongo
ArcadeDB provides support for both MongoDB Query Language and MongoDB protocol.
If you’re using ArcadeDB as embedded, please add the dependency to the arcadedb-mongodbw library.
If you’re using Maven include this dependency in your pom.xml file.
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-mongodbw</artifactId>
<version>26.10.1</version>
</dependency>
MongoDB Query Language
If you want to use MongoDB Query Language from Java API, you can simply keep the relevant jars in your classpath and execute a query or a command with "mongo" as language.
Example:
// CREATE A NEW DATABASE
Database database = new DatabaseFactory("heroes").create();
// CREATE THE DOCUMENT TYPE 'HEROES'
database.getSchema().createDocumentType("Heroes");
// CREATE A NEW DOCUMENT
database.transaction((tx) -> {
database.newDocument("Heroes").set("name", "Jay").set("lastName", "Miner").set("id", i).save();
});
// EXECUTE A QUERY USING MONGO AS QUERY LANGUAGE
for (ResultSet resultset = database.query("mongo", // <-- USE 'mongo' INSTEAD OF 'sql'
"{ collection: 'Heroes', query: { $and: [ { name: { $eq: 'Jay' } }, { lastName: { $exists: true } }, { lastName: { $eq: 'Miner' } }, { lastName: { $ne: 'Miner22' } } ], $orderBy: { id: 1 } } }"); resultset.hasNext(); ++i) {
Result doc = resultset.next();
...
}
For more information on the MongoDB query language see: MongoDB CRUD Operations
Mongo queries through Postgres Driver
You can execute a Mongo query against ArcadeDB server by using the Postgres driver and prefixing the query with {mongo}.
Example:
"{mongo} { collection: 'Heroes', query: { $and: [ { name: { $eq: 'Jay' } }, { lastName: { $exists: true } }, { lastName: { $eq: 'Miner' } } ] } }"
ArcadeDB server will execute the query { collection: 'Heroes', query: { $and: [ { name: { $eq: 'Jay' } }, { lastName: { $exists: true } }, { lastName: { $eq: 'Miner' } } ] } } using the Mongo query language.
Mongo queries through HTTP/JSON
You can execute a Mongo query against ArcadeDB server by using HTTP/JSON API. Example of executing an idempotent query with HTTP GET command:
curl "http://localhost:2480/query/graph/mongo/{ collection: 'Heroes', query: { $and: [ { name: { $eq: 'Jay' } }, { lastName: { $exists: true } }, { lastName: { $eq: 'Miner' } } ]} }"
You can also execute the same query in HTTP POST, passing the language and query in payload:
curl -X POST "http://localhost:2480/query/graph" -d "{'language': 'mongo', 'command': '{ collection: \"Heroes\", query: { $and: [ { name: { $eq: \"Jay\" } }, { lastName: { $exists: true } }, { lastName: { $eq: \"Miner\" } } ] } }\"}"
MongoDB Protocol Plugin
If your application is written for MongoDB and you’d like to run it with ArcadeDB instead, you can simply replace the MongoDB server with ArcadeDB server with the MongoDB Plugin installed. This plugin supports MongoDB BSON Network protocol. In this way you can use any MongoDB driver for any supported programming language.
ArcadeDB Server supports a subset of the MongoDB protocol, like CRUD operations and queries.
To start the MongoDB plugin, enlist it in the server.plugins settings.
To specify multiple plugins, use the comma , as separator.
Example to start ArcadeDB with the MongoDB Plugin:
~/arcadedb $ bin/server.sh -Darcadedb.server.plugins="MongoDB:com.arcadedb.mongo.MongoDBProtocolPlugin"
If you’re using MS Windows OS, replace server.sh with server.bat.
In case you’re running ArcadeDB with Docker, use -e to pass settings (Port 27017 is the default MongoDB binary port):
docker run --rm -p 2480:2480 -p27017:27017 \
--env ARCADEDB_SETTINGS="-Darcadedb.server.rootPassword=playwithdata \
-Darcadedb.server.plugins=MongoDB:com.arcadedb.mongo.MongoDBProtocolPlugin " \
arcadedata/arcadedb:latest
The Server output will contain this line:
2018-10-09 18:47:01:692 INFO <ArcadeDB_0> - MongoDB Protocol plugin started [ArcadeDBServer]
Supported commands
The plugin implements a subset of the MongoDB protocol, focused on CRUD operations, queries and index creation:
| Command | Driver helpers |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Updating and deleting documents
The update and delete commands accept the same filter operators as find ($eq, $ne, $lt, $lte, $gt, $gte, $in, $nin, $and, $or, $not, $exists, …).
// Delete the first matching document
db.doc.deleteOne({ test: { $eq: "abcde" } })
// Delete all matching documents
db.doc.deleteMany({ counter: { $gte: 5 } })
// Replace the whole document (replaceOne / replaceMany)
db.doc.replaceOne({ test: { $eq: "abcde" } }, { test: "vwxyz" })
// Update with operators ($set, $unset, $inc)
db.doc.updateOne({ test: "v2" }, { $set: { name: "Jay" } })
db.doc.updateMany({ counter: { $gte: 8 } }, { $inc: { counter: 100 } })
db.doc.updateOne({ test: "v1" }, { $unset: { counter: "" } })
// Upsert: insert when nothing matches
db.doc.updateOne({ test: "missing" }, { $set: { counter: 999 } }, { upsert: true })
Notes:
-
deleteOne(),updateOne()andreplaceOne()affect a single matching document;deleteMany()andupdateMany()affect all matches. -
A replacement document (no
$-prefixed keys) fully replaces the matched document’s fields, but keeps its_id. The_idis immutable: an update or replacement that changes or removes it is refused (error 66). -
The supported update operators are
$set,$unsetand$inc. They accept dotted paths ({ $set: { "addr.city": "Rome" } }): the embedded document is updated and missing levels are created. Writing below a value that is not a document (for example a string) is refused. -
With
upsert: true, when no document matches a new one is inserted, seeded from the filter’s equality conditions plus the update. If the filter includes an_id, that_idis used for the new document; otherwise one is generated. Either way, the resulting_idis returned.
Null values, projections, regular expressions and duplicate keys
-
$ne,$nin,$in(withnull) and$notalso match documents whose field isnullor missing, like MongoDB. For example{ age: { $ne: 30 } }returns documents with noage. -
Filters follow MongoDB’s rules for types and arrays, in
find,count,updateanddelete. A number never equals a string or a boolean ({ n: 5 }does not match"5"), and$gt/$ltcompare within one type only. A filter on an array field tests its elements:{ tags: "a" }matches["a", "b"],{ tags: { $ne: "a" } }does not, and$all,$elemMatch,$sizeandtags.0work.$existsworks on dotted paths ({ "a.b": { $exists: false } }), and collection names with dots (fs.files) can be read like any other. -
A filter on
_id(equality or$in) uses the unique_idindex. A filter on any other field is tested on the documents with MongoDB’s own rules, and an index narrows which documents are tested only for a field that an index starts with and whose type is declared in the schema as a scalar (STRING,BOOLEAN,BYTE,SHORT,INTEGER,LONGorDOUBLE; for exampleCREATE PROPERTY products.sku STRINGfollowed byCREATE INDEX ON products (sku) UNIQUE). Equality and$inuse the index, and so does a range ($gt,$gte,$lt,$lte) on an integer field, when the operand is of the kind of the field (a string for aSTRING, an integer for anINTEGER). Lookups, updates, deletes and bulk upserts by such a field do not read the whole collection. A field the schema does not declare is never narrowed by its index, because an array can be stored in it and an index does not see the elements of an array: filters on it, and on dotted paths, negations, regular expressions and temporal values, read every document of the collection and are slower on large ones. The declared type is relied upon: when you declare a property on a collection that already holds data, records stored before the declaration are not converted, so rewrite them if they hold an array or a value of another kind in that field. -
A top-level
$not,$exprand a$regexdirectly inside$elemMatchare refused with an error. Regular expressions are time-bounded byarcadedb.command.regexTimeout, shared by all the documents one command scans: raise it if a big scan with a regular expression times out. The same bound applies to the$matchstages of an aggregation, includingcountDocuments()with a filter, and to the$matchstages nested in$facet,$lookupand$unionWith. A non-regex$exprworks inside an aggregation$match. -
Aggregating or counting a collection that does not exist returns an empty result, and the first insert creates the collection.
-
find()honors the projection ({ name: 1 },{ _id: 0 },{ age: 0 }, dotted paths). Inclusion and exclusion cannot be mixed, except for_id. Projection operators ($slice,$elemMatch,$meta) are not supported and return an error. Documents never contain ArcadeDB’s@rid,@typeor@cat. -
Regular expressions work as literals (
/^a/i) and with$regexand$options(i,m,s,x), also under$not. An invalid pattern returns an error. -
_idis unique: inserting an existing_idfails withE11000. In a batch,ordered: true(the default) stops at the first duplicate,ordered: falseinserts the others. The first insert creates the collection and a unique index on_id; on a big existing collection that first insert builds the index and other writes to it wait until it is done. -
The
_idindex keys follow the_idtype (integers, doubles, strings or ObjectIds), so range queries and sorts on numeric ids are numeric. If a collection mixes kinds of_id, the index uses string keys:1and"1"are then the same key, and ordering is textual.
|
A String |
BSON value types
Besides strings, numbers, booleans, dates, embedded documents and arrays, the plugin stores and returns these BSON types with their type kept: binary, regular expression, timestamp, MinKey, MaxKey, JavaScript code, Decimal128 and ObjectId. A value the server cannot store is refused with an error instead of being dropped.
-
Decimal128 is stored as an exact decimal. A decimal with more than 34 digits, written through SQL, is returned as a double.
-
An ObjectId outside
_idis stored as the text$oid:<24 hex digits>and returned as an ObjectId. Filters (eq,$ne,$in) also match the plain hex text stored by older versions._idkeeps the plain hex form. -
Binary, timestamp, regular expression, MinKey, MaxKey and JavaScript values are stored as a small document with the reserved field
$bson. Equality and$inwork on them, but range queries and sorting do not follow BSON order. -
Reserved names: a field called
$bsonis refused, and a text starting with$oid:or$str:is escaped on write, so it comes back unchanged. -
The Symbol type and binary subtypes other than 0 and 4 are not supported by the bundled MongoDB library.
Authentication
The MongoDB Protocol Plugin supports authentication through the SASL PLAIN mechanism (RFC 4616).
Credentials are validated against the ArcadeDB server users, exactly like the PostgreSQL protocol.
Because ArcadeDB stores passwords as one-way hashes, the challenge-response mechanisms SCRAM-SHA-1 and SCRAM-SHA-256 (the default negotiated by most MongoDB drivers and by mongosh) cannot be supported: they would require the clear-text password to be available on the server side.
For this reason the client must explicitly request the PLAIN mechanism.
Example using a connection string:
mongosh "mongodb://root:playwithdata@localhost:27017/mydb?authMechanism=PLAIN"
Or, from an already opened shell:
db.auth({ user: "root", pwd: "playwithdata", mechanism: "PLAIN" })
The user and pwd are the ArcadeDB server credentials, and the authentication database is checked against the databases the user is authorized to access.
The PLAIN mechanism transmits the credentials in clear text. In production always use it over a TLS-encrypted connection, the same recommendation that applies to the PostgreSQL wire protocol.
|
Index management
The MongoDB Protocol Plugin supports the createIndexes command, used by the driver helpers createIndex() and createIndexes().
Each requested index is mapped to an ArcadeDB LSM-Tree index over the same property list.
// Single-field index
db.doc.createIndex({ test: 1 })
// Unique index
db.doc.createIndex({ email: 1 }, { unique: true })
// Compound index
db.doc.createIndex({ lastName: 1, firstName: -1 })
Notes:
-
If the target collection does not exist yet, it is created automatically (the response reports
createdCollectionAutomatically: true). -
Because MongoDB collections are schemaless, properties that are not yet declared on the type are kept free-form and the index serializes their keys as strings, preserving the stored value type.
-
The sort direction (
1ascending,-1descending) is accepted for compatibility but ignored: ArcadeDB LSM-Tree indexes can be scanned in both directions. -
Re-creating an existing index is a no-op, matching MongoDB semantics.
-
Specialized index types (
text,2dsphere,hashed, …) are created as standard LSM-Tree indexes on the indexed fields.