Db class
class Db{
final _log = new Logger('Db');
String databaseName;
String _debugInfo;
_ConnectionManager _connectionManager;
get _masterConnection => _connectionManager.masterConnection;
WriteConcern _writeConcern;
_validateDatabaseName(String dbName) {
if(dbName.length == 0) throw new MongoDartError('database name cannot be the empty string');
var invalidChars = [" ", ".", "\$", "/", "\\"];
for(var i = 0; i < invalidChars.length; i++) {
if(dbName.indexOf(invalidChars[i]) != -1) throw new Exception("database names cannot contain the character '${invalidChars[i]}'");
}
}
String toString() => 'Db($databaseName,$_debugInfo)';
/**
* Db constructor expects [valid mongodb URI] (http://www.mongodb.org/display/DOCS/Connections).
* For example next code points to local mongodb server on default mongodb port, database *testdb*
* var db = new Db('mongodb://127.0.0.1/testdb');
* And that code direct to MongoLab server on 37637 port, database *testdb*, username *dart*, password *test*
* var db = new Db('mongodb://dart:test@ds037637-a.mongolab.com:37637/objectory_blog');
*/
Db(String uriString, [this._debugInfo]){
_connectionManager = new _ConnectionManager(this);
_connectionManager.addConnection(_parseUri(uriString));
}
Db.pool(List<String> uriList, [this._debugInfo]) {
_connectionManager = new _ConnectionManager(this);
uriList.forEach((uri) {
_connectionManager.addConnection(_parseUri(uri));
});
}
ServerConfig _parseUri(String uriString) {
var uri = Uri.parse(uriString);
if (uri.scheme != 'mongodb') {
throw new MongoDartError('Invalid scheme in uri: $uriString ${uri.scheme}');
}
var serverConfig = new ServerConfig();
serverConfig.host = uri.host;
serverConfig.port = uri.port;
if (serverConfig.port == null || serverConfig.port == 0){
serverConfig.port = 27017;
}
if (uri.userInfo != '') {
var userInfo = uri.userInfo.split(':');
if (userInfo.length != 2) {
throw new MongoDartError('Неверный формат поля userInfo: $uri.userInfo');
}
serverConfig.userName = userInfo[0];
serverConfig.password = userInfo[1];
}
if (uri.path != '') {
databaseName = uri.path.replaceAll('/','');
}
return serverConfig;
}
DbCollection collection(String collectionName){
return new DbCollection(this,collectionName);
}
Future queryMessage(MongoMessage queryMessage, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
return connection.query(queryMessage);
}
executeMessage(MongoMessage message, WriteConcern writeConcern, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
if (writeConcern == null) {
writeConcern = _writeConcern;
}
connection.execute(message,writeConcern == WriteConcern.ERRORS_IGNORED);
}
Future open({WriteConcern writeConcern: WriteConcern.ACKNOWLEDGED}){
_writeConcern = writeConcern;
return _connectionManager.open(writeConcern);
}
Future executeDbCommand(MongoMessage message, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
Completer<Map> result = new Completer();
connection.query(message).then((replyMessage){
String errMsg;
if (replyMessage.documents.length == 0) {
errMsg = "Error executing Db command, Document length 0 $replyMessage";
print("Error: $errMsg");
var m = new Map();
m["errmsg"]=errMsg;
result.completeError(m);
} else if (replyMessage.documents[0]['ok'] == 1.0 && replyMessage.documents[0]['err'] == null){
result.complete(replyMessage.documents[0]);
} else {
result.completeError(replyMessage.documents[0]);
}
});
return result.future;
}
Future dropCollection(String collectionName){
Completer completer = new Completer();
collectionsInfoCursor(collectionName).toList().then((v){
if (v.length == 1){
executeDbCommand(DbCommand.createDropCollectionCommand(this,collectionName))
.then((res)=>completer.complete(res));
} else{
completer.complete(true);
}
});
return completer.future;
}
/**
* Drop current database
*/
Future drop(){
return executeDbCommand(DbCommand.createDropDatabaseCommand(this));
}
Future removeFromCollection(String collectionName, [Map selector = const {}, WriteConcern writeConcern]){
executeMessage(new MongoRemoveMessage("$databaseName.$collectionName", selector),writeConcern);
return _getAcknowledgement(writeConcern: writeConcern);
}
Future<Map> getLastError({bool j: false, int w: 0}){
return executeDbCommand(DbCommand.createGetLastErrorCommand(this, j: j, w: w));
}
Future<Map> getNonce({_Connection connection}){
return executeDbCommand(DbCommand.createGetNonceCommand(this), connection: connection);
}
Future<Map> isMaster({_Connection connection}){
return executeDbCommand(DbCommand.createIsMasterCommand(this), connection: connection);
}
Future<Map> wait(){
return getLastError();
}
Future close(){
_log.fine('$this closed');
return _connectionManager.close();
}
Cursor collectionsInfoCursor([String collectionName]) {
Map selector = {};
// If we are limiting the access to a specific collection name
if(collectionName != null){
selector["name"] = "${this.databaseName}.$collectionName";
}
// Return Cursor
return new Cursor(this, new DbCollection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector);
}
Future<bool> authenticate(String userName, String password, {_Connection connection}){
return getNonce(connection: connection).then((msg) {
var nonce = msg["nonce"];
var command = DbCommand.createAuthenticationCommand(this,userName,password,nonce);
return executeDbCommand(command, connection: connection);
}).then( (res) => res["ok"]==1 );
}
Future<List> indexInformation([String collectionName]) {
var selector = {};
if (collectionName != null) {
selector['ns'] = '$databaseName.$collectionName';
}
return new Cursor(this, new DbCollection(this, DbCommand.SYSTEM_INDEX_COLLECTION), selector).toList();
}
String _createIndexName(Map keys) {
var name = '';
keys.forEach((key,value) {
name = '${name}_${key}_$value';
});
return name;
}
Future createIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) {
var selector = {};
selector['ns'] = '$databaseName.$collectionName';
keys = _setKeys(key, keys);
selector['key'] = keys;
for (final order in keys.values) {
if (order != 1 && order != -1) {
throw new ArgumentError('Keys may contain only 1 or -1');
}
}
if (unique == true) {
selector['unique'] = true;
} else {
selector['unique'] = false;
}
if (sparse == true) {
selector['sparse'] = true;
}
if (background == true) {
selector['background'] = true;
}
if (dropDups == true) {
selector['dropDups'] = true;
}
if (name == null) {
name = _createIndexName(keys);
}
selector['name'] = name;
MongoInsertMessage insertMessage = new MongoInsertMessage('$databaseName.${DbCommand.SYSTEM_INDEX_COLLECTION}',[selector]);
executeMessage(insertMessage, _writeConcern);
return getLastError();
}
Map _setKeys(String key, Map keys) {
if (key != null && keys != null) {
throw new ArgumentError('Only one parameter must be set: key or keys');
}
if (key != null) {
keys = new Map();
keys['$key'] = 1;
}
if (keys == null) {
throw new ArgumentError('key or keys parameter must be set');
}
return keys;
}
Future ensureIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) {
keys = _setKeys(key, keys);
var completer = new Completer();
indexInformation(collectionName).then((indexInfos) {
if (name == null) {
name = _createIndexName(keys);
}
if (indexInfos.any((info) => info['name'] == name)) {
completer.complete({'ok': 1.0, 'result': 'index preexists'});
} else {
createIndex(collectionName,keys: keys, unique: unique, sparse: sparse, background: background, dropDups: dropDups, name: name)
.then((res)=>completer.complete(res));
}
});
return completer.future;
}
Future _getAcknowledgement({WriteConcern writeConcern}) {
if (writeConcern == null) {
writeConcern = _writeConcern;
}
if (writeConcern == WriteConcern.ERRORS_IGNORED) {
return new Future.value({'ok': 1.0});
}
else
{
return getLastError(j: writeConcern == WriteConcern.JOURNALED, w: min(1, writeConcern.value));
}
}
}
Constructors
new Db(String uriString, [String _debugInfo]) #
Db constructor expects valid mongodb URI. For example next code points to local mongodb server on default mongodb port, database testdb
var db = new Db('mongodb://127.0.0.1/testdb');
And that code direct to MongoLab server on 37637 port, database testdb, username dart, password test
var db = new Db('mongodb://dart:test@ds037637-a.mongolab.com:37637/objectory_blog');
Db(String uriString, [this._debugInfo]){
_connectionManager = new _ConnectionManager(this);
_connectionManager.addConnection(_parseUri(uriString));
}
Methods
Future<bool> authenticate(String userName, String password, {_Connection connection}) #
Future<bool> authenticate(String userName, String password, {_Connection connection}){
return getNonce(connection: connection).then((msg) {
var nonce = msg["nonce"];
var command = DbCommand.createAuthenticationCommand(this,userName,password,nonce);
return executeDbCommand(command, connection: connection);
}).then( (res) => res["ok"]==1 );
}
DbCollection collection(String collectionName) #
DbCollection collection(String collectionName){
return new DbCollection(this,collectionName);
}
Cursor collectionsInfoCursor([String collectionName]) #
Cursor collectionsInfoCursor([String collectionName]) {
Map selector = {};
// If we are limiting the access to a specific collection name
if(collectionName != null){
selector["name"] = "${this.databaseName}.$collectionName";
}
// Return Cursor
return new Cursor(this, new DbCollection(this, DbCommand.SYSTEM_NAMESPACE_COLLECTION), selector);
}
Future createIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) #
Future createIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) {
var selector = {};
selector['ns'] = '$databaseName.$collectionName';
keys = _setKeys(key, keys);
selector['key'] = keys;
for (final order in keys.values) {
if (order != 1 && order != -1) {
throw new ArgumentError('Keys may contain only 1 or -1');
}
}
if (unique == true) {
selector['unique'] = true;
} else {
selector['unique'] = false;
}
if (sparse == true) {
selector['sparse'] = true;
}
if (background == true) {
selector['background'] = true;
}
if (dropDups == true) {
selector['dropDups'] = true;
}
if (name == null) {
name = _createIndexName(keys);
}
selector['name'] = name;
MongoInsertMessage insertMessage = new MongoInsertMessage('$databaseName.${DbCommand.SYSTEM_INDEX_COLLECTION}',[selector]);
executeMessage(insertMessage, _writeConcern);
return getLastError();
}
Future drop() #
Drop current database
Future drop(){
return executeDbCommand(DbCommand.createDropDatabaseCommand(this));
}
Future dropCollection(String collectionName) #
Future dropCollection(String collectionName){
Completer completer = new Completer();
collectionsInfoCursor(collectionName).toList().then((v){
if (v.length == 1){
executeDbCommand(DbCommand.createDropCollectionCommand(this,collectionName))
.then((res)=>completer.complete(res));
} else{
completer.complete(true);
}
});
return completer.future;
}
Future ensureIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) #
Future ensureIndex(String collectionName, {String key, Map keys, bool unique, bool sparse, bool background, bool dropDups, String name}) {
keys = _setKeys(key, keys);
var completer = new Completer();
indexInformation(collectionName).then((indexInfos) {
if (name == null) {
name = _createIndexName(keys);
}
if (indexInfos.any((info) => info['name'] == name)) {
completer.complete({'ok': 1.0, 'result': 'index preexists'});
} else {
createIndex(collectionName,keys: keys, unique: unique, sparse: sparse, background: background, dropDups: dropDups, name: name)
.then((res)=>completer.complete(res));
}
});
return completer.future;
}
Future executeDbCommand(MongoMessage message, {_Connection connection}) #
Future executeDbCommand(MongoMessage message, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
Completer<Map> result = new Completer();
connection.query(message).then((replyMessage){
String errMsg;
if (replyMessage.documents.length == 0) {
errMsg = "Error executing Db command, Document length 0 $replyMessage";
print("Error: $errMsg");
var m = new Map();
m["errmsg"]=errMsg;
result.completeError(m);
} else if (replyMessage.documents[0]['ok'] == 1.0 && replyMessage.documents[0]['err'] == null){
result.complete(replyMessage.documents[0]);
} else {
result.completeError(replyMessage.documents[0]);
}
});
return result.future;
}
dynamic executeMessage(MongoMessage message, WriteConcern writeConcern, {_Connection connection}) #
executeMessage(MongoMessage message, WriteConcern writeConcern, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
if (writeConcern == null) {
writeConcern = _writeConcern;
}
connection.execute(message,writeConcern == WriteConcern.ERRORS_IGNORED);
}
Future<Map> getLastError({bool j: false, int w: 0}) #
Future<Map> getLastError({bool j: false, int w: 0}){
return executeDbCommand(DbCommand.createGetLastErrorCommand(this, j: j, w: w));
}
Future<Map> getNonce({_Connection connection}) #
Future<Map> getNonce({_Connection connection}){
return executeDbCommand(DbCommand.createGetNonceCommand(this), connection: connection);
}
Future<List> indexInformation([String collectionName]) #
Future<List> indexInformation([String collectionName]) {
var selector = {};
if (collectionName != null) {
selector['ns'] = '$databaseName.$collectionName';
}
return new Cursor(this, new DbCollection(this, DbCommand.SYSTEM_INDEX_COLLECTION), selector).toList();
}
Future<Map> isMaster({_Connection connection}) #
Future<Map> isMaster({_Connection connection}){
return executeDbCommand(DbCommand.createIsMasterCommand(this), connection: connection);
}
Future open({WriteConcern writeConcern: WriteConcern.ACKNOWLEDGED}) #
Future open({WriteConcern writeConcern: WriteConcern.ACKNOWLEDGED}){
_writeConcern = writeConcern;
return _connectionManager.open(writeConcern);
}
Future queryMessage(MongoMessage queryMessage, {_Connection connection}) #
Future queryMessage(MongoMessage queryMessage, {_Connection connection}){
if (connection == null) {
connection = _masterConnection;
}
return connection.query(queryMessage);
}
Future removeFromCollection(String collectionName, [Map selector = const{}, WriteConcern writeConcern]) #
Future removeFromCollection(String collectionName, [Map selector = const {}, WriteConcern writeConcern]){
executeMessage(new MongoRemoveMessage("$databaseName.$collectionName", selector),writeConcern);
return _getAcknowledgement(writeConcern: writeConcern);
}