mirror of https://gitee.com/bigwinds/arangodb
geo indexes
This commit is contained in:
parent
88bfe8f18c
commit
0479fd652f
|
@ -2660,30 +2660,222 @@ static v8::Handle<v8::Value> CreateVocBase (v8::Arguments const& argv,
|
|||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief index comparator, used by the coordinator to detect if two index
|
||||
/// contents are the same
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
static bool CompareGeoIndex1Coordinator (TRI_json_t const* lhs,
|
||||
TRI_json_t const* rhs) {
|
||||
if (! TRI_CheckSameValueJson(TRI_LookupArrayJson(lhs, "unique"),
|
||||
TRI_LookupArrayJson(rhs, "unique"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! TRI_CheckSameValueJson(TRI_LookupArrayJson(lhs, "fields"),
|
||||
TRI_LookupArrayJson(rhs, "fields"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! TRI_CheckSameValueJson(TRI_LookupArrayJson(lhs, "geoJson"),
|
||||
TRI_LookupArrayJson(rhs, "geoJson"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensure a geo index, coordinator case
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
static v8::Handle<v8::Value> EnsureGeoIndex1Coordinator (TRI_vocbase_col_t const* col,
|
||||
bool create,
|
||||
bool unique,
|
||||
bool geoJson,
|
||||
bool ignoreNull,
|
||||
char const* location) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
string const databaseName(col->_dbName);
|
||||
string const cid = StringUtils::itoa(col->_cid);
|
||||
|
||||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
if (json == 0) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "type", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, "geo1"));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "unique", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "geoJson", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, geoJson));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
|
||||
|
||||
if (unique) {
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, ignoreNull));
|
||||
}
|
||||
|
||||
TRI_json_t* flds = TRI_CreateList2Json(TRI_UNKNOWN_MEM_ZONE, 1);
|
||||
|
||||
if (flds == 0) {
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, flds, TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, location));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "fields", flds);
|
||||
|
||||
TRI_json_t* resultJson = 0;
|
||||
string errorMsg;
|
||||
int myerrno = ci->ensureIndexCoordinator(databaseName,
|
||||
cid,
|
||||
json,
|
||||
create,
|
||||
&CompareGeoIndex1Coordinator,
|
||||
resultJson,
|
||||
errorMsg,
|
||||
360.0);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
if (myerrno != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, myerrno, errorMsg);
|
||||
}
|
||||
|
||||
if (resultJson == 0) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
// TODO: protect against races on _name
|
||||
v8::Handle<v8::Value> index = IndexRep(col->_name, resultJson);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, resultJson);
|
||||
|
||||
return scope.Close(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief index comparator, used by the coordinator to detect if two index
|
||||
/// contents are the same
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
static bool CompareGeoIndex2Coordinator (TRI_json_t const* lhs,
|
||||
TRI_json_t const* rhs) {
|
||||
if (! TRI_CheckSameValueJson(TRI_LookupArrayJson(lhs, "unique"),
|
||||
TRI_LookupArrayJson(rhs, "unique"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! TRI_CheckSameValueJson(TRI_LookupArrayJson(lhs, "fields"),
|
||||
TRI_LookupArrayJson(rhs, "fields"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensure a geo index, coordinator case
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
static v8::Handle<v8::Value> EnsureGeoIndex2Coordinator (TRI_vocbase_col_t const* col,
|
||||
bool create,
|
||||
bool unique,
|
||||
bool ignoreNull,
|
||||
char const* latitude,
|
||||
char const* longitude) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
string const databaseName(col->_dbName);
|
||||
string const cid = StringUtils::itoa(col->_cid);
|
||||
|
||||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
|
||||
TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
if (json == 0) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "type", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, "geo2"));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "unique", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
|
||||
|
||||
if (unique) {
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, ignoreNull));
|
||||
}
|
||||
|
||||
TRI_json_t* flds = TRI_CreateList2Json(TRI_UNKNOWN_MEM_ZONE, 2);
|
||||
|
||||
if (flds == 0) {
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, flds, TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, latitude));
|
||||
TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, flds, TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, longitude));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "fields", flds);
|
||||
|
||||
TRI_json_t* resultJson = 0;
|
||||
string errorMsg;
|
||||
int myerrno = ci->ensureIndexCoordinator(databaseName,
|
||||
cid,
|
||||
json,
|
||||
create,
|
||||
&CompareGeoIndex2Coordinator,
|
||||
resultJson,
|
||||
errorMsg,
|
||||
360.0);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
if (myerrno != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, myerrno, errorMsg);
|
||||
}
|
||||
|
||||
if (resultJson == 0) {
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
// TODO: protect against races on _name
|
||||
v8::Handle<v8::Value> index = IndexRep(col->_name, resultJson);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, resultJson);
|
||||
|
||||
return scope.Close(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a geo index or constraint exists
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv, bool unique) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
||||
PREVENT_EMBEDDED_TRANSACTION(scope);
|
||||
|
||||
TRI_vocbase_col_t const* col = TRI_UnwrapClass<TRI_vocbase_col_t>(argv.Holder(), WRP_VOCBASE_COL_TYPE);
|
||||
|
||||
v8::Handle<v8::Object> err;
|
||||
TRI_vocbase_col_t const* collection = UseCollection(argv.Holder(), &err);
|
||||
|
||||
if (collection == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
if (col == 0) {
|
||||
TRI_V8_EXCEPTION_INTERNAL(scope, "cannot extract collection");
|
||||
}
|
||||
|
||||
TRI_primary_collection_t* primary = collection->_collection;
|
||||
|
||||
TRI_document_collection_t* document = (TRI_document_collection_t*) primary;
|
||||
TRI_vocbase_t* vocbase = col->_vocbase;
|
||||
assert(vocbase != 0);
|
||||
|
||||
TRI_index_t* idx = 0;
|
||||
bool created;
|
||||
int off = unique ? 1 : 0;
|
||||
bool ignoreNull = false;
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// case: <location>
|
||||
// .............................................................................
|
||||
|
@ -2692,15 +2884,30 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
|
|||
TRI_Utf8ValueNFC loc(TRI_UNKNOWN_MEM_ZONE, argv[0]);
|
||||
|
||||
if (*loc == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<location> must be an attribute path");
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
ignoreNull = TRI_ObjectToBoolean(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
v8::Handle<v8::Value> ret = EnsureGeoIndex1Coordinator(col, true, unique, false, ignoreNull, *loc);
|
||||
return scope.Close(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
ReadTransactionType trx(vocbase, resolver, col->_cid);
|
||||
|
||||
idx = TRI_EnsureGeoIndex1DocumentCollection(document,
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION(scope, res);
|
||||
}
|
||||
|
||||
idx = TRI_EnsureGeoIndex1DocumentCollection((TRI_document_collection_t*) trx.primaryCollection(),
|
||||
*loc,
|
||||
false,
|
||||
unique,
|
||||
|
@ -2717,15 +2924,30 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
|
|||
TRI_Utf8ValueNFC loc(TRI_UNKNOWN_MEM_ZONE, argv[0]);
|
||||
|
||||
if (*loc == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<location> must be an attribute path");
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
ignoreNull = TRI_ObjectToBoolean(argv[2]);
|
||||
}
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
v8::Handle<v8::Value> ret = EnsureGeoIndex1Coordinator(col, true, unique, TRI_ObjectToBoolean(argv[1]), ignoreNull, *loc);
|
||||
return scope.Close(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
ReadTransactionType trx(vocbase, resolver, col->_cid);
|
||||
|
||||
idx = TRI_EnsureGeoIndex1DocumentCollection(document,
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION(scope, res);
|
||||
}
|
||||
|
||||
idx = TRI_EnsureGeoIndex1DocumentCollection((TRI_document_collection_t*) trx.primaryCollection(),
|
||||
*loc,
|
||||
TRI_ObjectToBoolean(argv[1]),
|
||||
unique,
|
||||
|
@ -2743,20 +2965,34 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
|
|||
TRI_Utf8ValueNFC lon(TRI_UNKNOWN_MEM_ZONE, argv[1]);
|
||||
|
||||
if (*lat == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<latitude> must be an attribute path");
|
||||
}
|
||||
|
||||
if (*lon == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<longitude> must be an attribute path");
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
ignoreNull = TRI_ObjectToBoolean(argv[2]);
|
||||
}
|
||||
|
||||
#ifdef TRI_ENABLE_CLUSTER
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
v8::Handle<v8::Value> ret = EnsureGeoIndex2Coordinator(col, true, unique, ignoreNull, *lat, *lon);
|
||||
return scope.Close(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
ReadTransactionType trx(vocbase, resolver, col->_cid);
|
||||
|
||||
idx = TRI_EnsureGeoIndex2DocumentCollection(document,
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_EXCEPTION(scope, res);
|
||||
}
|
||||
|
||||
idx = TRI_EnsureGeoIndex2DocumentCollection((TRI_document_collection_t*) trx.primaryCollection(),
|
||||
*lat,
|
||||
*lon,
|
||||
unique,
|
||||
|
@ -2770,8 +3006,6 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
|
|||
// .............................................................................
|
||||
|
||||
else {
|
||||
ReleaseCollection(collection);
|
||||
|
||||
if (unique) {
|
||||
TRI_V8_EXCEPTION_USAGE(
|
||||
scope,
|
||||
|
@ -2786,25 +3020,24 @@ static v8::Handle<v8::Value> EnsureGeoIndexVocbaseCol (v8::Arguments const& argv
|
|||
}
|
||||
|
||||
if (idx == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_errno(), "index could not be created");
|
||||
}
|
||||
|
||||
TRI_json_t* json = idx->json(idx,false);
|
||||
|
||||
if (json == 0) {
|
||||
ReleaseCollection(collection);
|
||||
TRI_V8_EXCEPTION_MEMORY(scope);
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> index = IndexRep(&primary->base, json);
|
||||
// TODO: protect this from races on _name!!
|
||||
v8::Handle<v8::Value> index = IndexRep(col->_name, json);
|
||||
|
||||
TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
|
||||
|
||||
if (index->IsObject()) {
|
||||
index->ToObject()->Set(v8::String::New("isNewlyCreated"), v8::Boolean::New(created));
|
||||
}
|
||||
|
||||
ReleaseCollection(collection);
|
||||
return scope.Close(index);
|
||||
}
|
||||
|
||||
|
|
|
@ -380,6 +380,58 @@ function handleDatabaseChanges (plan, current) {
|
|||
cleanupCurrentDatabases();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an index in a shard
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function createIndex (shard, index) {
|
||||
var collection = arangodb.db._collection(shard);
|
||||
|
||||
switch (index.type) {
|
||||
case "hash":
|
||||
if (index.unique) {
|
||||
collection.ensureUniqueConstraint.apply(collection, index.fields);
|
||||
}
|
||||
else {
|
||||
collection.ensureHashIndex.apply(collection, index.fields);
|
||||
}
|
||||
break;
|
||||
case "skiplist":
|
||||
if (index.unique) {
|
||||
collection.ensureUniqueSkiplist.apply(collection, index.fields);
|
||||
}
|
||||
else {
|
||||
collection.ensureSkiplist.apply(collection, index.fields);
|
||||
}
|
||||
break;
|
||||
case "fulltext":
|
||||
collection.ensureFulltextIndex(index.fields[0], index.minLength);
|
||||
break;
|
||||
case "geo1":
|
||||
if (index.unique) {
|
||||
collection.ensureGeoConstraint(index.fields[0],
|
||||
index.geoJson,
|
||||
index.ignoreNull);
|
||||
}
|
||||
else {
|
||||
collection.ensureGeoIndex(index.fields[0],
|
||||
index.geoJson,
|
||||
index.ignoreNull);
|
||||
}
|
||||
break;
|
||||
case "geo2":
|
||||
if (index.unique) {
|
||||
collection.ensureGeoConstraint(index.fields[0],
|
||||
index.fields[1],
|
||||
index.ignoreNull);
|
||||
}
|
||||
else {
|
||||
collection.ensureGeoIndex(index.fields[0], index.fields[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create collections if they exist in the plan but not locally
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -526,35 +578,15 @@ function createLocalCollections (plannedCollections) {
|
|||
|
||||
for (idx in payload.indexes) {
|
||||
if (payload.indexes.hasOwnProperty(idx)) {
|
||||
if (! indexes.hasOwnProperty(payload.indexes[idx].id)) {
|
||||
var c = db._collection(shard);
|
||||
|
||||
var index = payload.indexes[idx];
|
||||
|
||||
if (! indexes.hasOwnProperty(index.id)) {
|
||||
console.info("creating index '%s/%s': %s",
|
||||
database,
|
||||
shard,
|
||||
JSON.stringify(payload.indexes[idx]));
|
||||
JSON.stringify(index));
|
||||
|
||||
switch (payload.indexes[idx].type) {
|
||||
case "hash":
|
||||
if (payload.indexes[idx].unique) {
|
||||
c.ensureUniqueConstraint.apply(c, payload.indexes[idx].fields);
|
||||
}
|
||||
else {
|
||||
c.ensureHashIndex.apply(c, payload.indexes[idx].fields);
|
||||
}
|
||||
break;
|
||||
case "skiplist":
|
||||
if (payload.indexes[idx].unique) {
|
||||
c.ensureUniqueSkiplist.apply(c, payload.indexes[idx].fields);
|
||||
}
|
||||
else {
|
||||
c.ensureSkiplist.apply(c, payload.indexes[idx].fields);
|
||||
}
|
||||
break;
|
||||
case "fulltext":
|
||||
c.ensureFulltextIndex(payload.indexes[idx].fields[0], payload.indexes[idx].minLength);
|
||||
break;
|
||||
}
|
||||
createIndex(shard, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue