Example #1
0
ArangoCollection.prototype.any = function () {
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
      
    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put", 
                                     "shard:" + shard, 
                                     dbName, 
                                     "/_api/simple/any", 
                                     JSON.stringify({ 
                                       collection: shard 
                                     }), 
                                     { }, 
                                     options);
    });

    var results = cluster.wait(coord, shards), i;
    for (i = 0; i < results.length; ++i) {
      var body = JSON.parse(results[i].body);
      if (body.document !== null) {
        return body.document;
      }
    }

    return null;
  }

  return this.ANY();
};
Example #2
0
ArangoCollection.prototype.truncate = function () {
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    if (this.status() === ArangoCollection.STATUS_UNLOADED) {
      this.load();
    }
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
      
    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put", 
                                     "shard:" + shard, 
                                     dbName, 
                                     "/_api/collection/" + encodeURIComponent(shard) + "/truncate",
                                     "", 
                                     { }, 
                                     options);
    });

    cluster.wait(coord, shards);
    return;
  }

  return this.TRUNCATE();
};
Example #3
0
function getEdges (collection, vertex, direction) {
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, collection.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
     
    if (vertex !== null &&
        typeof vertex === "object" && 
        vertex.hasOwnProperty("_id")) {
      vertex = vertex._id;
    }
 
    shards.forEach(function (shard) {
      var url = "/_api/edges/" + encodeURIComponent(shard) +
                "?direction=" + encodeURIComponent(direction) + 
                "&vertex=" + encodeURIComponent(vertex);

      ArangoClusterComm.asyncRequest("get", 
                                     "shard:" + shard, 
                                     dbName, 
                                     url,
                                     "",
                                     { }, 
                                     options);
    });

    var results = cluster.wait(coord, shards), i;
    var edges = [ ];

    for (i = 0; i < results.length; ++i) {
      var body = JSON.parse(results[i].body);
     
      edges = edges.concat(body.edges);
    }

    return edges;
  }

  if (direction === "in") {
    return collection.INEDGES(vertex);
  }
  if (direction === "out") {
    return collection.OUTEDGES(vertex);
  }
  
  return collection.EDGES(vertex);
}
Example #4
0
ArangoCollection.prototype.last = function (count) {
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this.name());

    if (shards.length !== 1) {
      var err = new ArangoError();
      err.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
      err.errorMessage = "operation is not supported in sharded collections";

      throw err;
    }

    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    var shard = shards[0];

    ArangoClusterComm.asyncRequest("put", 
                                   "shard:" + shard, 
                                   dbName, 
                                   "/_api/simple/last", 
                                   JSON.stringify({ 
                                     collection: shard,
                                     count: count 
                                   }), 
                                   { }, 
                                   options);

    var results = cluster.wait(coord, shards);

    if (results.length) {
      var body = JSON.parse(results[0].body);
      return body.result || null;
    }
  }
  else {
    return this.LAST(count);
  }

  return null; 
};
Example #5
0
SimpleQueryNear.prototype.execute = function () {
  var documents;
  var result;
  var limit;
  var i, n;

  if (this._execution !== null) {
    return;
  }

  if (this._skip === null) {
    this._skip = 0;
  }

  if (this._skip < 0) {
    var err = new ArangoError();
    err.errorNum = internal.errors.ERROR_BAD_PARAMETER;
    err.errorMessage = "skip must be non-negative";
    throw err;
  }

  if (this._limit === null) {
    limit = this._skip + 100;
  }
  else {
    limit = this._skip + this._limit;
  }

  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this._collection.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    var _limit = 0;
    if (this._limit > 0) {
      if (this._skip >= 0) {
        _limit = this._skip + this._limit;
      }
    }

    var attribute;
    if (this._distance !== null) {
      attribute = this._distance;
    }
    else {
      // use a pseudo-attribute for distance (we need this for sorting)
      attribute = "$distance";
    }

    var self = this;
    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put",
                                     "shard:" + shard,
                                     dbName,
                                     "/_api/simple/near",
                                     JSON.stringify({
                                       collection: shard,
                                       latitude: self._latitude,
                                       longitude: self._longitude,
                                       distance: attribute,
                                       geo: rewriteIndex(self._index),
                                       skip: 0,
                                       limit: _limit || undefined,
                                       batchSize: 100000000
                                     }),
                                     { },
                                     options);
    });

    var _documents = [ ], total = 0;
    result = cluster.wait(coord, shards);

    result.forEach(function(part) {
      var body = JSON.parse(part.body);
      total += body.total;

      _documents = _documents.concat(body.result);
    });

    if (shards.length > 1) {
      _documents.sort(function (l, r) {
        if (l[attribute] === r[attribute]) {
          return 0;
        }
        return (l[attribute] < r[attribute] ? -1 : 1);
      });
    }

    if (this._limit > 0) {
      _documents = _documents.slice(0, this._skip + this._limit);
    }

    if (this._distance === null) {
      n = _documents.length;
      for (i = 0; i < n; ++i) {
        delete _documents[i][attribute];
      }
    }

    documents = {
      documents: _documents,
      count: _documents.length,
      total: total
    };
  }
  else {
    result = this._collection.NEAR(this._index, this._latitude, this._longitude, limit);

    documents = {
      documents: result.documents,
      count: result.documents.length,
      total: result.documents.length
    };

    if (this._distance !== null) {
      var distances = result.distances;
      n = documents.documents.length;
      for (i = this._skip;  i < n;  ++i) {
        documents.documents[i][this._distance] = distances[i];
      }
    }
  }

  this._execution = new GeneralArrayCursor(documents.documents, this._skip, null);
  this._countQuery = documents.total - this._skip;
  this._countTotal = documents.total;
};
Example #6
0
SimpleQueryAll.prototype.execute = function () {
  if (this._execution === null) {
    if (this._skip === null) {
      this._skip = 0;
    }

    var documents;
    var cluster = require("org/arangodb/cluster");

    if (cluster.isCoordinator()) {
      var dbName = require("internal").db._name();
      var shards = cluster.shardList(dbName, this._collection.name());
      var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
      var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
      var limit = 0;
      if (this._limit > 0) {
        if (this._skip >= 0) {
          limit = this._skip + this._limit;
        }
      }

      shards.forEach(function (shard) {
        ArangoClusterComm.asyncRequest("put",
                                       "shard:" + shard,
                                       dbName,
                                       "/_api/simple/all",
                                       JSON.stringify({
                                         collection: shard,
                                         skip: 0,
                                         limit: limit || undefined,
                                         batchSize: 100000000
                                       }),
                                       { },
                                       options);
      });

      var _documents = [ ], total = 0;
      var result = cluster.wait(coord, shards);
      var toSkip = this._skip, toLimit = this._limit;

      if (toSkip < 0) {
        // negative skip is special
        toLimit = null;
      }

      result.forEach(function(part) {
        var body = JSON.parse(part.body);
        total += body.count;

        if (toSkip > 0) {
          if (toSkip >= body.result.length) {
            toSkip -= body.result.length;
            return;
          }

          body.result = body.result.slice(toSkip);
          toSkip = 0;
        }

        if (toLimit !== null && toLimit !== undefined) {
          if (body.result.length >= toLimit) {
            body.result = body.result.slice(0, toLimit);
            toLimit = 0;
          }
          else {
            toLimit -= body.result.length;
          }
        }

        _documents = _documents.concat(body.result);
      });

      if (this._skip < 0) {
        // apply negative skip
        var start = _documents.length + this._skip;
        _documents = _documents.slice(start, start + (this._limit || 100000000));
      }

      documents = {
        documents: _documents,
        count: _documents.length,
        total: total
      };
    }
    else {
      documents = this._collection.ALL(this._skip, this._limit);
    }

    this._execution = new GeneralArrayCursor(documents.documents);
    this._countQuery = documents.count;
    this._countTotal = documents.total;
  }
};
Example #7
0
function rangedQuery (collection, attribute, left, right, type, skip, limit) {
  var documents;
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, collection.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    var _limit = 0;
    if (limit > 0) {
      if (skip >= 0) {
        _limit = skip + limit;
      }
    }

    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put",
                                     "shard:" + shard,
                                     dbName,
                                     "/_api/simple/range",
                                     JSON.stringify({
                                       collection: shard,
                                       attribute: attribute,
                                       left: left,
                                       right: right,
                                       closed: type,
                                       skip: 0,
                                       limit: _limit || undefined,
                                       batchSize: 100000000
                                     }),
                                     { },
                                     options);
    });

    var _documents = [ ], total = 0;
    var result = cluster.wait(coord, shards);

    result.forEach(function(part) {
      var body = JSON.parse(part.body);
      total += body.count;

      _documents = _documents.concat(body.result);
    });

    if (shards.length > 1) {
      var cmp = require("org/arangodb/aql").RELATIONAL_CMP;
      _documents.sort(function (l, r) {
        return cmp(l[attribute], r[attribute]);
      });
    }

    if (limit > 0 && skip >= 0) {
      _documents = _documents.slice(skip, skip + limit);
    }
    else if (skip > 0) {
      _documents = _documents.slice(skip, _documents.length);
    }
    else if (skip < 0) {
      // apply negative skip
      var start = _documents.length + skip;
      _documents = _documents.slice(start, start + (limit || 100000000));
    }

    documents = {
      documents: _documents,
      count: _documents.length,
      total: total
    };
  }
  else {
    var idx = collection.lookupSkiplist(attribute);

    if (idx === null) {
      idx = collection.lookupUniqueSkiplist(attribute);

      if (idx !== null) {
        console.debug("found unique skip-list index %s", idx.id);
      }
    }
    else {
      console.debug("found skip-list index %s", idx.id);
    }

    if (idx !== null) {
      var cond = {};

      if (type === 0) {
        cond[attribute] = [ [ ">=", left ], [ "<", right ] ];
      }
      else if (type === 1) {
        cond[attribute] = [ [ ">=", left ], [ "<=", right ] ];
      }
      else {
        throw "unknown type";
      }

      documents = collection.BY_CONDITION_SKIPLIST(idx.id, cond, skip, limit);
    }
    else {
      throw "not implemented";
    }
  }

  return documents;
}
Example #8
0
SimpleQueryFulltext.prototype.execute = function () {
  var result;
  var documents;

  if (this._execution !== null) {
    return;
  }

  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this._collection.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    var _limit = 0;
    if (this._limit > 0) {
      if (this._skip >= 0) {
        _limit = this._skip + this._limit;
      }
    }

    var self = this;
    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put",
                                     "shard:" + shard,
                                     dbName,
                                     "/_api/simple/fulltext",
                                     JSON.stringify({
                                       collection: shard,
                                       attribute: self._attribute,
                                       query: self._query,
                                       index: rewriteIndex(self._index),
                                       skip: 0,
                                       limit: _limit || undefined,
                                       batchSize: 100000000
                                     }),
                                     { },
                                     options);
    });

    var _documents = [ ], total = 0;
    result = cluster.wait(coord, shards);

    result.forEach(function(part) {
      var body = JSON.parse(part.body);
      total += body.total;

      _documents = _documents.concat(body.result);
    });

    if (this._limit > 0) {
      _documents = _documents.slice(0, this._skip + this._limit);
    }

    documents = {
      documents: _documents,
      count: _documents.length,
      total: total
    };
  }
  else {
    result = this._collection.FULLTEXT(this._index, this._query);

    documents = {
      documents: result.documents,
      count: result.documents.length - this._skip,
      total: result.documents.length
    };

    if (this._limit > 0) {
      documents.documents = documents.documents.slice(0, this._skip + this._limit);
    }
  }

  this._execution = new GeneralArrayCursor(documents.documents, this._skip, null);
  this._countQuery = documents.total - this._skip;
  this._countTotal = documents.total;
};
Example #9
0
SimpleQueryWithinRectangle.prototype.execute = function () {
  var result;
  var documents;

  if (this._execution !== null) {
    return;
  }

  if (this._skip === null) {
    this._skip = 0;
  }

  if (this._skip < 0) {
    var err = new ArangoError();
    err.errorNum = internal.errors.ERROR_BAD_PARAMETER;
    err.errorMessage = "skip must be non-negative";
    throw err;
  }

  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this._collection.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    var _limit = 0;
    if (this._limit > 0) {
      if (this._skip >= 0) {
        _limit = this._skip + this._limit;
      }
    }

    var self = this;
    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put",
                                     "shard:" + shard,
                                     dbName,
                                     "/_api/simple/within-rectangle",
                                     JSON.stringify({
                                       collection: shard,
                                       latitude1: self._latitude1,
                                       longitude1: self._longitude1,
                                       latitude2: self._latitude2,
                                       longitude2: self._longitude2,
                                       geo: rewriteIndex(self._index),
                                       skip: 0,
                                       limit: _limit || undefined,
                                       batchSize: 100000000
                                     }),
                                     { },
                                     options);
    });

    var _documents = [ ], total = 0;
    result = cluster.wait(coord, shards);

    result.forEach(function(part) {
      var body = JSON.parse(part.body);
      total += body.total;

      _documents = _documents.concat(body.result);
    });

    if (this._limit > 0) {
      _documents = _documents.slice(0, this._skip + this._limit);
    }

    documents = {
      documents: _documents,
      count: _documents.length,
      total: total
    };
  }
  else {
    var distanceMeters = function (lat1, lon1, lat2, lon2) {  
      var deltaLat = (lat2 - lat1) * Math.PI / 180;
      var deltaLon = (lon2 - lon1) * Math.PI / 180;
      var a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
              Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
              Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
      var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

      return 6378.137 /* radius of earth in kilometers */  
             * c 
             * 1000; // kilometers to meters;
    };

    var diameter = distanceMeters(this._latitude1, this._longitude1, this._latitude2, this._longitude2);
    var midpoint = [ 
      this._latitude1 + (this._latitude2 - this._latitude1) * 0.5, 
      this._longitude1 + (this._longitude2 - this._longitude1) * 0.5 
    ];

    result = this._collection.WITHIN(this._index, midpoint[0], midpoint[1], diameter);

    var idx = this._collection.index(this._index);
    var latLower, latUpper, lonLower, lonUpper;

    if (this._latitude1 < this._latitude2) {
      latLower = this._latitude1;
      latUpper = this._latitude2;
    }
    else {
      latLower = this._latitude2;
      latUpper = this._latitude1;
    }

    if (this._longitude1 < this._longitude2) {
      lonLower = this._longitude1;
      lonUpper = this._longitude2;
    }
    else {
      lonLower = this._longitude2;
      lonUpper = this._longitude1;
    }
  
    documents = [ ];
    if (idx.type === 'geo1') {
      // geo1, we have both coordinates in a list
      var attribute = idx.fields[0];
      if (idx.geoJson) {
        result.documents.forEach(function(doc) {
          // check if within bounding rectangle
          // first list value is longitude, then latitude
          if (doc[attribute][1] >= latLower && doc[attribute][1] <= latUpper &&
              doc[attribute][0] >= lonLower && doc[attribute][0] <= lonUpper) {
            documents.push(doc);
          }
        });
      }
      else {
        result.documents.forEach(function(doc) {
          // check if within bounding rectangle
          // first list value is latitude, then longitude
          if (doc[attribute][0] >= latLower && doc[attribute][0] <= latUpper &&
              doc[attribute][1] >= lonLower && doc[attribute][1] <= lonUpper) {
            documents.push(doc);
          }
        });
      }
    }
    else {
      // geo2, we have dedicated latitude and longitude attributes
      var latAtt = idx.fields[0], lonAtt = idx.fields[1];
      result.documents.forEach(function(doc) {
        // check if within bounding rectangle
        if (doc[latAtt] >= latLower && doc[latAtt] <= latUpper &&
            doc[lonAtt] >= lonLower && doc[lonAtt] <= lonUpper) {
          documents.push(doc);
        }
      });
    }
    
    documents = {
      documents: documents,
      count: result.documents.length,
      total: result.documents.length
    };
    
    if (this._limit > 0) {
      documents.documents = documents.documents.slice(0, this._skip + this._limit);
      documents.count = documents.documents.length;
    }

  }

  this._execution = new GeneralArrayCursor(documents.documents, this._skip, null);
  this._countQuery = documents.total - this._skip;
  this._countTotal = documents.total;
};
Example #10
0
ArangoCollection.prototype.updateByExample = function (example, 
                                                       newValue, 
                                                       keepNull, 
                                                       waitForSync, 
                                                       limit) {
  
  if (limit === 0) {
    return 0;
  }
  
  if (typeof newValue !== "object" || Array.isArray(newValue)) {
    var err1 = new ArangoError();
    err1.errorNum = internal.errors.ERROR_BAD_PARAMETER.code;
    err1.errorMessage = "invalid value for parameter 'newValue'";

    throw err1;
  }

  if (typeof keepNull === "object") {
    if (typeof waitForSync !== "undefined") {
      throw "too many parameters";
    }
    var tmp_options = keepNull === null ? {} : keepNull;

    // avoiding jslint error
    // see: http://jslinterrors.com/unexpected-sync-method-a/
    /*jslint node: true, stupid: true */
    keepNull = tmp_options.keepNull;
    waitForSync = tmp_options.waitForSync;
    limit = tmp_options.limit;
  }
  
  var cluster = require("org/arangodb/cluster");

  if (cluster.isCoordinator()) {
    var dbName = require("internal").db._name();
    var shards = cluster.shardList(dbName, this.name());
    var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
    var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
    
    if (limit > 0 && shards.length > 1) {
      var err2 = new ArangoError();
      err2.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
      err2.errorMessage = "limit is not supported in sharded collections";

      throw err2;
    }

    shards.forEach(function (shard) {
      ArangoClusterComm.asyncRequest("put", 
                                     "shard:" + shard, 
                                     dbName, 
                                     "/_api/simple/update-by-example", 
                                     JSON.stringify({ 
                                       collection: shard,
                                       example: example,
                                       newValue: newValue,
                                       waitForSync: waitForSync,
                                       keepNull: keepNull,
                                       limit: limit || undefined
                                     }), 
                                     { }, 
                                     options);
    });

    var updated = 0;
    var results = cluster.wait(coord, shards), i;
    for (i = 0; i < results.length; ++i) {
      var body = JSON.parse(results[i].body);

      updated += (body.updated || 0);
    }

    return updated;
  }

  return require("internal").db._executeTransaction({
    collections: {
      write: this.name()
    },
    action: function (params) {
      var collection = params.c;
      var documents = collection.byExample(params.example);
      if (params.limit > 0) {
        documents = documents.limit(params.limit);
      }

      var updated = 0;
      while (documents.hasNext()) {
        var document = documents.next();

        if (collection.update(document, params.newValue, 
            {overwrite: true, keepNull: params.keepNull, waitForSync: params.wfs})) {
          updated++;
        }
      }
      return updated;
    },
    params: {
      c: this,
      example: example,
      newValue: newValue,
      keepNull: keepNull,
      limit: limit,
      wfs: waitForSync
    }
  });
};