1
0
Fork 0

adjusted geo index API

This commit is contained in:
Jan Steemann 2015-02-18 14:59:46 +01:00
parent 76bb6a52c9
commit f29591135a
18 changed files with 284 additions and 753 deletions

View File

@ -119,6 +119,14 @@ v2.5.0-alpha2 (2015-02-16)
db.collection.ensureUniqueSkiplist(attributeName, { sparse: true });
db.collection.ensureUniqueSkiplist(attributeName1, attributeName2, { sparse: true });
Note that in place of the above specialized index creation commands, it is recommended to use
the more general index creation command `ensureIndex`:
```js
db.collection.ensureIndex({ type: "hash", sparse: true, unique: true, fields: [ attributeName ] });
db.collection.ensureIndex({ type: "skiplist", sparse: false, unique: false, fields: [ "a", "b" ] });
```
When not explicitly set, the `sparse` attribute defaults to `false` for new indexes.
This causes a change in behavior when creating a unique hash index without specifying the
@ -129,7 +137,18 @@ v2.5.0-alpha2 (2015-02-16)
only be created sparse if sparsity is explicitly requested. Existing unique hash indexes from 2.4
or before will automatically be migrated so they are still sparse after the upgrade to 2.5.
Indexes other than hash and skiplist do not support sparsity.
Geo indexes are implicitly sparse, meaning documents without the indexed location attribute or
containing invalid location coordinate values will be excluded from the index automatically. This
is also a change when compared to pre-2.5 behavior, when documents with missing or invalid
coordinate values may have caused errors on insertion when the geo index' `unique` flag was set
and its `ignoreNull` flag was not.
This was confusing and has been rectified in 2.5. The method `ensureGeoConstaint()` now does the
same as `ensureGeoIndex()`. Furthermore, the attributes `constraint`, `unique`, `ignoreNull` and
`sparse` flags are now completely ignored when creating geo indexes.
The same is true for fulltext indexes. There is no need to specify non-uniqueness or sparsity for
geo or fulltext indexes. They will always be non-unique and sparse.
As sparse indexes may exclude some documents, they cannot be used for every type of query.
Sparse hash indexes cannot be used to find documents for which at least one of the indexed

View File

@ -52,7 +52,16 @@ db.collection.ensureUniqueSkiplist(attributeName, { sparse: true });
db.collection.ensureUniqueSkiplist(attributeName1, attributeName2, { sparse: true });
```
When not explicitly set, the `sparse` attribute defaults to `false` for new indexes.
Note that in place of the above specialized index creation commands, it is recommended to use
the more general index creation command `ensureIndex`:
```js
db.collection.ensureIndex({ type: "hash", sparse: true, unique: true, fields: [ attributeName ] });
db.collection.ensureIndex({ type: "skiplist", sparse: false, unique: false, fields: [ "a", "b" ] });
```
When not explicitly set, the `sparse` attribute defaults to `false` for new hash or
skiplist indexes.
This causes a change in behavior when creating a unique hash index without specifying the
sparse flag: in 2.4, unique hash indexes were implicitly sparse, always excluding `null` values.
@ -61,8 +70,18 @@ hash indexes nor skiplists in 2.4. This implicit sparsity of unique hash indexes
an inconsistency, and therefore the behavior was cleaned up in 2.5. As of 2.5, indexes will
only be created sparse if sparsity is explicitly requested. Existing unique hash indexes from 2.4
or before will automatically be migrated so they are still sparse after the upgrade to 2.5.
Other indexes than hash and skiplist do not support sparsity.
Geo indexes are implicitly sparse, meaning documents without the indexed location attribute or
containing invalid location coordinate values will be excluded from the index automatically. This
is also a change when compared to pre-2.5 behavior, when documents with missing or invalid
coordinate values may have caused errors on insertion when the geo index' `unique` flag was set
and its `ignoreNull` flag was not. This was confusing and has been rectified in 2.5. The method
`ensureGeoConstaint()` now does the same as `ensureGeoIndex()`. Furthermore, the attributes
`constraint`, `unique`, `ignoreNull` and `sparse` flags are now completely ignored when creating
geo indexes.
The same is true for fulltext indexes. There is no need to specify non-uniqueness or sparsity for
geo or fulltext indexes.
As sparse indexes may exclude some documents, they cannot be used for every type of query.
Sparse hash indexes cannot be used to find documents for which at least one of the indexed

View File

@ -8,8 +8,8 @@ upgrading to ArangoDB 2.5, and adjust any client programs if necessary.
!SUBSECTION Sparse indexes
Hash indexes and skiplist indexes can now be created sparse. When not explicitly set, the
`sparse` attribute defaults to `false` for new indexes.
Hash indexes and skiplist indexes can now be created in a sparse variant.
When not explicitly set, the `sparse` attribute defaults to `false` for new indexes.
This causes a change in behavior when creating a unique hash index without specifying the
sparse flag. The unique hash index will be created in a non-sparse variant in ArangoDB 2.5.
@ -19,14 +19,29 @@ from the index. There was no option to control this behavior, and sparsity was n
for non-unique hash indexes nor skiplists in 2.4. This implicit sparsity of just unique hash
indexes was considered an inconsistency, and therefore the behavior was cleaned up in 2.5.
As of 2.5, indexes will only be created sparse if sparsity is explicitly requested. This may
require a change in index-creating client code, but only if the client code creates unique hash
indexes and if they are still intended to be sparse. In this case, the client code should
explicitly set the `sparse` flag to `true` when creating a unique hash index.
As of 2.5, hash and skiplist indexes will only be created sparse if sparsity is explicitly requested.
This may require a change in index-creating client code, but only if the client code creates
unique hash indexes and if they are still intended to be sparse. In this case, the client code
should explicitly set the `sparse` flag to `true` when creating a unique hash index.
Existing unique hash indexes from 2.4 or before will automatically be migrated so they are still
sparse after the upgrade to 2.5. For the indexes, the `sparse` attribute will be populated
automatically with a value of `true`.
sparse after the upgrade to 2.5. For these indexes, the `sparse` attribute will be populated
automatically with a value of `true`.
Geo indexes are implicitly sparse, meaning documents without the indexed location attribute or
containing invalid location coordinate values will be excluded from the index automatically. This
is also a change when compared to pre-2.5 behavior, when documents with missing or invalid
coordinate values may have caused errors on insertion when the geo index' `unique` flag was set
and its `ignoreNull` flag was not.
This was confusing and has been rectified in 2.5. The method `ensureGeoConstaint()` now does the
same as `ensureGeoIndex()`. Furthermore, the attributes `constraint`, `unique`, `ignoreNull` and
`sparse` flags are now completely ignored when creating geo indexes. Client index creation code
therefore does not need to set the `ignoreNull` or `constraint` attributes when creating a geo
index.
The same is true for fulltext indexes. There is no need to specify non-uniqueness or sparsity for
geo or fulltext indexes. They will always be non-unique and sparse.
!SECTION Deprecated features

View File

@ -179,6 +179,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "a" ])
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
doc = ArangoDB.log_post("#{prefix}-create-old-geo", cmd, :body => body)
@ -192,6 +194,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "a" ])
doc.parsed_response['isNewlyCreated'].should eq(false)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with location" do
@ -209,6 +213,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "b" ])
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with location and geo-json = true" do
@ -226,6 +232,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "c" ])
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with location and geo-json = false" do
@ -243,6 +251,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "d" ])
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with latitude and longitude" do
@ -259,6 +269,8 @@ describe ArangoDB do
doc.parsed_response['fields'].should eq([ "e", "f" ])
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with constraint" do
@ -274,8 +286,10 @@ describe ArangoDB do
doc.parsed_response['type'].should eq("geo1")
doc.parsed_response['geoJson'].should eq(true)
doc.parsed_response['fields'].should eq([ "c" ])
doc.parsed_response['unique'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
it "creating geo index with constraint" do
@ -290,8 +304,10 @@ describe ArangoDB do
doc.parsed_response['id'].should match(@reFull)
doc.parsed_response['type'].should eq("geo2")
doc.parsed_response['fields'].should eq([ "c", "d" ])
doc.parsed_response['unique'].should eq(true)
doc.parsed_response['unique'].should eq(false)
doc.parsed_response['isNewlyCreated'].should eq(true)
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
end
@ -349,6 +365,8 @@ describe ArangoDB do
doc.parsed_response['type'].should eq("geo1")
doc.parsed_response['geoJson'].should eq(false)
doc.parsed_response['fields'].should eq([ "a" ])
doc.parsed_response['sparse'].should eq(true)
doc.parsed_response['ignoreNull'].should eq(true)
end
end

View File

@ -258,11 +258,10 @@ static TRI_json_t* JsonGeo1Index (TRI_index_t const* idx) {
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "geoJson", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, geo->_geoJson));
// "constraint" and "unique" are identical for geo indexes.
// we return "constraint" just for downwards-compatibility
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, idx->_unique));
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, idx->_ignoreNull));
// "constraint" is always false as of ArangoDB 2.5
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, false));
// "ignoreNull" is always true as of ArangoDB 2.5
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
TRI_json_t* fields = TRI_CreateArrayJson(TRI_CORE_MEM_ZONE, 1);
TRI_PushBack3ArrayJson(TRI_CORE_MEM_ZONE, fields, TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, location, strlen(location)));
@ -300,11 +299,10 @@ static TRI_json_t* JsonGeo2Index (TRI_index_t const* idx) {
return nullptr;
}
// "constraint" and "unique" are identical for geo indexes.
// we return "constraint" just for downwards-compatibility
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, idx->_unique));
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, geo->base._ignoreNull));
// "constraint" is always false as of ArangoDB 2.5
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, false));
// "ignoreNull" is always true as of ArangoDB 2.5
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
TRI_json_t* fields = TRI_CreateArrayJson(TRI_CORE_MEM_ZONE, 2);
TRI_PushBack3ArrayJson(TRI_CORE_MEM_ZONE, fields, TRI_CreateStringCopyJson(TRI_CORE_MEM_ZONE, latitude, strlen(latitude)));
@ -351,23 +349,12 @@ static int InsertGeoIndex (TRI_index_t* idx,
}
if (! ok) {
if (idx->_unique) {
if (idx->_ignoreNull && missing) {
return TRI_ERROR_NO_ERROR;
}
else {
return TRI_set_errno(TRI_ERROR_ARANGO_GEO_INDEX_VIOLATED);
}
}
else {
return TRI_ERROR_NO_ERROR;
}
return TRI_ERROR_NO_ERROR;
}
// and insert into index
gc.latitude = latitude;
gc.longitude = longitude;
gc.data = CONST_CAST(doc);
res = GeoIndex_insert(geo->_geoIndex, &gc);
@ -380,13 +367,8 @@ static int InsertGeoIndex (TRI_index_t* idx,
return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
}
else if (res == -3) {
if (idx->_unique) {
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
return TRI_set_errno(TRI_ERROR_ARANGO_GEO_INDEX_VIOLATED);
}
else {
return TRI_ERROR_NO_ERROR;
}
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
return TRI_ERROR_NO_ERROR;
}
else if (res < 0) {
return TRI_set_errno(TRI_ERROR_INTERNAL);
@ -428,7 +410,6 @@ static int RemoveGeoIndex (TRI_index_t* idx,
if (ok) {
gc.latitude = latitude;
gc.longitude = longitude;
gc.data = CONST_CAST(doc);
// ignore non-existing elements in geo-index
@ -450,9 +431,7 @@ TRI_index_t* TRI_CreateGeo1Index (TRI_document_collection_t* document,
TRI_idx_iid_t iid,
char const* locationName,
TRI_shape_pid_t location,
bool geoJson,
bool unique,
bool ignoreNull) {
bool geoJson) {
char* ln;
TRI_geo_index_t* geo = static_cast<TRI_geo_index_t*>(TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(TRI_geo_index_t), false));
@ -460,9 +439,7 @@ TRI_index_t* TRI_CreateGeo1Index (TRI_document_collection_t* document,
TRI_InitVectorString(&idx->_fields, TRI_CORE_MEM_ZONE);
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_GEO1_INDEX, document, false, unique);
idx->_ignoreNull = ignoreNull;
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_GEO1_INDEX, document, true, false);
idx->memory = MemoryGeoIndex;
idx->json = JsonGeo1Index;
idx->insert = InsertGeoIndex;
@ -498,9 +475,7 @@ TRI_index_t* TRI_CreateGeo2Index (TRI_document_collection_t* document,
char const* latitudeName,
TRI_shape_pid_t latitude,
char const* longitudeName,
TRI_shape_pid_t longitude,
bool unique,
bool ignoreNull) {
TRI_shape_pid_t longitude) {
char* lat;
char* lon;
@ -509,9 +484,7 @@ TRI_index_t* TRI_CreateGeo2Index (TRI_document_collection_t* document,
TRI_InitVectorString(&idx->_fields, TRI_CORE_MEM_ZONE);
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_GEO2_INDEX, document, false, unique);
idx->_ignoreNull = ignoreNull;
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_GEO2_INDEX, document, true, false);
idx->memory = MemoryGeoIndex;
idx->json = JsonGeo2Index;
idx->insert = InsertGeoIndex;

View File

@ -50,8 +50,6 @@ TRI_index_t* TRI_CreateGeo1Index (struct TRI_document_collection_t*,
TRI_idx_iid_t,
char const*,
TRI_shape_pid_t,
bool,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
@ -63,9 +61,7 @@ TRI_index_t* TRI_CreateGeo2Index (struct TRI_document_collection_t*,
char const*,
TRI_shape_pid_t ,
char const*,
TRI_shape_pid_t,
bool,
bool);
TRI_shape_pid_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief frees the memory allocated, but does not free the pointer

View File

@ -219,28 +219,10 @@ static int ProcessIndexSparseFlag (v8::Isolate* isolate,
static int ProcessIndexUniqueFlag (v8::Isolate* isolate,
v8::Handle<v8::Object> const obj,
TRI_json_t* json,
bool fillConstraint = false) {
TRI_json_t* json) {
v8::HandleScope scope(isolate);
bool unique = ExtractBoolFlag(isolate, obj, TRI_V8_ASCII_STRING("unique"), false);
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "unique", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
if (fillConstraint) {
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, unique));
}
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief process the ignoreNull flag and add it to the json
////////////////////////////////////////////////////////////////////////////////
static int ProcessIndexIgnoreNullFlag (v8::Isolate* isolate,
v8::Handle<v8::Object> const obj,
TRI_json_t* json) {
v8::HandleScope scope(isolate);
bool ignoreNull = ExtractBoolFlag(isolate, obj, TRI_V8_ASCII_STRING("ignoreNull"), false);
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, ignoreNull));
return TRI_ERROR_NO_ERROR;
}
@ -254,8 +236,12 @@ static int EnhanceJsonIndexGeo1 (v8::Isolate* isolate,
TRI_json_t* json,
bool create) {
int res = ProcessIndexFields(isolate, obj, json, 1, create);
ProcessIndexUniqueFlag(isolate, obj, json, true);
ProcessIndexIgnoreNullFlag(isolate, obj, json);
if (ServerState::instance()->isCoordinator()) {
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false));
}
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "sparse", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "unique", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false));
ProcessIndexGeoJsonFlag(isolate, obj, json);
return res;
}
@ -269,8 +255,13 @@ static int EnhanceJsonIndexGeo2 (v8::Isolate* isolate,
TRI_json_t* json,
bool create) {
int res = ProcessIndexFields(isolate, obj, json, 2, create);
ProcessIndexUniqueFlag(isolate, obj, json, true);
ProcessIndexIgnoreNullFlag(isolate, obj, json);
if (ServerState::instance()->isCoordinator()) {
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "ignoreNull", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "constraint", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false));
}
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "sparse", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, json, "unique", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false));
ProcessIndexGeoJsonFlag(isolate, obj, json);
return res;
}
@ -642,12 +633,6 @@ static void EnsureIndexLocal (const v8::FunctionCallbackInfo<v8::Value>& args,
TRI_ASSERT(attributes._length == 1);
bool ignoreNull = false;
TRI_json_t* value = TRI_LookupObjectJson(json, "ignoreNull");
if (TRI_IsBooleanJson(value)) {
ignoreNull = value->_value._boolean;
}
bool geoJson = false;
value = TRI_LookupObjectJson(json, "geoJson");
if (TRI_IsBooleanJson(value)) {
@ -659,16 +644,12 @@ static void EnsureIndexLocal (const v8::FunctionCallbackInfo<v8::Value>& args,
iid,
(char const*) TRI_AtVectorPointer(&attributes, 0),
geoJson,
unique,
ignoreNull,
&created);
}
else {
idx = TRI_LookupGeoIndex1DocumentCollection(document,
(char const*) TRI_AtVectorPointer(&attributes, 0),
geoJson,
unique,
ignoreNull);
geoJson);
}
break;
}
@ -682,27 +663,17 @@ static void EnsureIndexLocal (const v8::FunctionCallbackInfo<v8::Value>& args,
TRI_ASSERT(attributes._length == 2);
bool ignoreNull = false;
TRI_json_t const* value = TRI_LookupObjectJson(json, "ignoreNull");
if (TRI_IsBooleanJson(value)) {
ignoreNull = value->_value._boolean;
}
if (create) {
idx = TRI_EnsureGeoIndex2DocumentCollection(document,
iid,
(char const*) TRI_AtVectorPointer(&attributes, 0),
(char const*) TRI_AtVectorPointer(&attributes, 1),
unique,
ignoreNull,
&created);
}
else {
idx = TRI_LookupGeoIndex2DocumentCollection(document,
(char const*) TRI_AtVectorPointer(&attributes, 0),
(char const*) TRI_AtVectorPointer(&attributes, 1),
unique,
ignoreNull);
(char const*) TRI_AtVectorPointer(&attributes, 1));
}
break;
}

View File

@ -3710,8 +3710,6 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
char const* latitude,
char const* longitude,
bool geoJson,
bool unique,
bool ignoreNull,
TRI_idx_iid_t iid,
bool* created) {
TRI_index_t* idx;
@ -3757,10 +3755,10 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
// check, if we know the index
if (location != nullptr) {
idx = TRI_LookupGeoIndex1DocumentCollection(document, location, geoJson, unique, ignoreNull);
idx = TRI_LookupGeoIndex1DocumentCollection(document, location, geoJson);
}
else if (longitude != nullptr && latitude != nullptr) {
idx = TRI_LookupGeoIndex2DocumentCollection(document, latitude, longitude, unique, ignoreNull);
idx = TRI_LookupGeoIndex2DocumentCollection(document, latitude, longitude);
}
else {
TRI_set_errno(TRI_ERROR_INTERNAL);
@ -3780,14 +3778,14 @@ static TRI_index_t* CreateGeoIndexDocumentCollection (TRI_document_collection_t*
// create a new index
if (location != nullptr) {
idx = TRI_CreateGeo1Index(document, iid, location, loc, geoJson, unique, ignoreNull);
idx = TRI_CreateGeo1Index(document, iid, location, loc, geoJson);
LOG_TRACE("created geo-index for location '%s': %ld",
location,
(unsigned long) loc);
}
else if (longitude != nullptr && latitude != nullptr) {
idx = TRI_CreateGeo2Index(document, iid, latitude, lat, longitude, lon, unique, ignoreNull);
idx = TRI_CreateGeo2Index(document, iid, latitude, lat, longitude, lon);
LOG_TRACE("created geo-index for location '%s': %ld, %ld",
location,
@ -3837,8 +3835,6 @@ static int GeoIndexFromJson (TRI_document_collection_t* document,
TRI_json_t* type;
TRI_json_t* bv;
TRI_json_t* fld;
bool unique;
bool ignoreNull;
char const* typeStr;
size_t fieldCount;
@ -3861,31 +3857,6 @@ static int GeoIndexFromJson (TRI_document_collection_t* document,
return TRI_errno();
}
// extract unique
unique = false;
// first try "unique" attribute
bv = TRI_LookupObjectJson(definition, "unique");
if (bv != nullptr && bv->_type == TRI_JSON_BOOLEAN) {
unique = bv->_value._boolean;
}
else {
// then "constraint"
bv = TRI_LookupObjectJson(definition, "constraint");
if (TRI_IsBooleanJson(bv)) {
unique = bv->_value._boolean;
}
}
// extract ignore null
ignoreNull = false;
bv = TRI_LookupObjectJson(definition, "ignoreNull");
if (TRI_IsBooleanJson(bv)) {
ignoreNull = bv->_value._boolean;
}
// list style
if (TRI_EqualString(typeStr, "geo1")) {
bool geoJson;
@ -3907,8 +3878,6 @@ static int GeoIndexFromJson (TRI_document_collection_t* document,
nullptr,
nullptr,
geoJson,
unique,
ignoreNull,
iid,
nullptr);
@ -3937,8 +3906,6 @@ static int GeoIndexFromJson (TRI_document_collection_t* document,
lat->_value._string.data,
lon->_value._string.data,
false,
unique,
ignoreNull,
iid,
nullptr);
@ -3973,9 +3940,7 @@ static int GeoIndexFromJson (TRI_document_collection_t* document,
TRI_index_t* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collection_t* document,
char const* location,
bool geoJson,
bool unique,
bool ignoreNull) {
bool geoJson) {
TRI_shaper_t* shaper = document->getShaper(); // ONLY IN INDEX, PROTECTED by RUNTIME
TRI_shape_pid_t loc = shaper->lookupAttributePathByName(shaper, location);
@ -3993,11 +3958,8 @@ TRI_index_t* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collection_t* d
TRI_geo_index_t* geo = (TRI_geo_index_t*) idx;
if (geo->_location != 0 && geo->_location == loc &&
geo->_geoJson == geoJson &&
idx->_unique == unique) {
if (! unique || geo->base._ignoreNull == ignoreNull) {
return idx;
}
geo->_geoJson == geoJson) {
return idx;
}
}
}
@ -4011,9 +3973,7 @@ TRI_index_t* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collection_t* d
TRI_index_t* TRI_LookupGeoIndex2DocumentCollection (TRI_document_collection_t* document,
char const* latitude,
char const* longitude,
bool unique,
bool ignoreNull) {
char const* longitude) {
TRI_shaper_t* shaper = document->getShaper(); // ONLY IN INDEX, PROTECTED by RUNTIME
TRI_shape_pid_t lat = shaper->lookupAttributePathByName(shaper, latitude);
@ -4034,11 +3994,8 @@ TRI_index_t* TRI_LookupGeoIndex2DocumentCollection (TRI_document_collection_t* d
if (geo->_latitude != 0 &&
geo->_longitude != 0 &&
geo->_latitude == lat &&
geo->_longitude == lon &&
idx->_unique == unique) {
if (! unique || geo->base._ignoreNull == ignoreNull) {
return idx;
}
geo->_longitude == lon) {
return idx;
}
}
}
@ -4054,8 +4011,6 @@ TRI_index_t* TRI_EnsureGeoIndex1DocumentCollection (TRI_document_collection_t* d
TRI_idx_iid_t iid,
char const* location,
bool geoJson,
bool unique,
bool ignoreNull,
bool* created) {
TRI_ReadLockReadWriteLock(&document->_vocbase->_inventoryLock);
@ -4065,7 +4020,7 @@ TRI_index_t* TRI_EnsureGeoIndex1DocumentCollection (TRI_document_collection_t* d
TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document);
TRI_index_t* idx = CreateGeoIndexDocumentCollection(document, location, nullptr, nullptr, geoJson, unique, ignoreNull, iid, created);
TRI_index_t* idx = CreateGeoIndexDocumentCollection(document, location, nullptr, nullptr, geoJson, iid, created);
if (idx != nullptr) {
if (created) {
@ -4096,8 +4051,6 @@ TRI_index_t* TRI_EnsureGeoIndex2DocumentCollection (TRI_document_collection_t* d
TRI_idx_iid_t iid,
char const* latitude,
char const* longitude,
bool unique,
bool ignoreNull,
bool* created) {
TRI_ReadLockReadWriteLock(&document->_vocbase->_inventoryLock);
@ -4107,7 +4060,7 @@ TRI_index_t* TRI_EnsureGeoIndex2DocumentCollection (TRI_document_collection_t* d
TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document);
TRI_index_t* idx = CreateGeoIndexDocumentCollection(document, nullptr, latitude, longitude, false, unique, ignoreNull, iid, created);
TRI_index_t* idx = CreateGeoIndexDocumentCollection(document, nullptr, latitude, longitude, false, iid, created);
if (idx != nullptr) {
if (created) {

View File

@ -818,8 +818,6 @@ TRI_index_t* TRI_EnsureCapConstraintDocumentCollection (TRI_document_collection_
struct TRI_index_s* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collection_t*,
char const*,
bool,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////
@ -830,9 +828,7 @@ struct TRI_index_s* TRI_LookupGeoIndex1DocumentCollection (TRI_document_collecti
struct TRI_index_s* TRI_LookupGeoIndex2DocumentCollection (TRI_document_collection_t*,
char const*,
char const*,
bool,
bool);
char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief ensures that a geo index exists, list style
@ -842,8 +838,6 @@ struct TRI_index_s* TRI_EnsureGeoIndex1DocumentCollection (TRI_document_collecti
TRI_idx_iid_t,
char const*,
bool,
bool,
bool,
bool*);
////////////////////////////////////////////////////////////////////////////////
@ -854,8 +848,6 @@ struct TRI_index_s* TRI_EnsureGeoIndex2DocumentCollection (TRI_document_collecti
TRI_idx_iid_t,
char const*,
char const*,
bool,
bool,
bool*);
// -----------------------------------------------------------------------------

View File

@ -436,11 +436,11 @@ TRI_json_t* TRI_JsonIndex (TRI_memory_zone_t* zone,
TRI_Insert3ObjectJson(zone, json, "type", TRI_CreateStringCopyJson(zone, TRI_TypeNameIndex(idx->_type), strlen(TRI_TypeNameIndex(idx->_type))));
TRI_Insert3ObjectJson(zone, json, "unique", TRI_CreateBooleanJson(zone, idx->_unique));
if (idx->_type == TRI_IDX_TYPE_HASH_INDEX ||
idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
if (idx->_type != TRI_IDX_TYPE_CAP_CONSTRAINT) {
// only show sparse flag for these index types, as it can't be set on others
TRI_Insert3ObjectJson(zone, json, "sparse", TRI_CreateBooleanJson(zone, idx->_sparse));
}
if (idx->_hasSelectivityEstimate) {
TRI_Insert3ObjectJson(zone, json, "selectivityEstimate", TRI_CreateNumberJson(zone, idx->selectivityEstimate(idx)));
}
@ -1783,7 +1783,7 @@ TRI_index_t* TRI_CreateFulltextIndex (TRI_document_collection_t* document,
idx = &fulltextIndex->base;
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_FULLTEXT_INDEX, document, false, false);
TRI_InitIndex(idx, iid, TRI_IDX_TYPE_FULLTEXT_INDEX, document, true, false);
idx->memory = MemoryFulltextIndex;
idx->json = JsonFulltextIndex;
@ -1874,20 +1874,6 @@ bool IndexComparator (TRI_json_t const* lhs,
return false;
}
}
value = TRI_LookupObjectJson(lhs, "ignoreNull");
if (TRI_IsBooleanJson(value)) {
if (! TRI_CheckSameValueJson(value, TRI_LookupObjectJson(rhs, "ignoreNull"))) {
return false;
}
}
}
else if (type == TRI_IDX_TYPE_GEO2_INDEX) {
value = TRI_LookupObjectJson(lhs, "ignoreNull");
if (TRI_IsBooleanJson(value)) {
if (! TRI_CheckSameValueJson(value, TRI_LookupObjectJson(rhs, "ignoreNull"))) {
return false;
}
}
}
else if (type == TRI_IDX_TYPE_FULLTEXT_INDEX) {
// minLength

View File

@ -99,7 +99,6 @@ typedef struct TRI_index_s {
TRI_vector_string_t _fields;
bool _unique;
bool _ignoreNull;
bool _sparse;
bool _hasSelectivityEstimate;

View File

@ -314,22 +314,14 @@ function get_api_index (req, res) {
/// followed by latitude. This corresponds to the format described in
/// http://geojson.org/geojson-spec.html#positions
///
/// - *constraint*: If *constraint* is *true*, then a geo-spatial
/// constraint is created. The constraint is a non-unique variant of the index.
/// **Note**: It is also possible to set the *unique* attribute instead of
/// the *constraint* attribute.
///
/// - *ignoreNull*: If a geo-spatial constraint is created and
/// *ignoreNull* is true, then documents with a null in *location* or at
/// least one null in *latitude* or *longitude* are ignored.
///
/// **Note**: Unique indexes on non-shard keys are not supported in a cluster.
/// Geo indexes are always sparse, meaning that documents that do not contain
/// the index attributes or have non-numeric values in the index attributes
/// will not be indexed.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// If the index already exists, then a *HTTP 200* is
/// returned.
/// If the index already exists, then a *HTTP 200* is returned.
///
/// @RESTRETURNCODE{201}
/// If the index does not already exist and could be created, then a *HTTP 201*
@ -348,7 +340,10 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "geo", "fields" : [ "b" ] }';
/// var body = {
/// type: "geo",
/// fields : [ "b" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -365,7 +360,10 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "geo", "fields" : [ "e", "f" ] }';
/// var body = {
/// type: "geo",
/// fields: [ "e", "f" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -443,7 +441,11 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "hash", "unique" : true, "fields" : [ "a", "b" ] }';
/// var body = {
/// type: "hash",
/// unique: true,
/// fields : [ "a", "b" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -460,7 +462,11 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "hash", "unique" : false, "fields" : [ "a", "b" ] }';
/// var body = {
/// type: "hash",
/// unique: false,
/// fields: [ "a", "b" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -477,7 +483,12 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "hash", "unique" : false, "sparse" : true, "fields" : [ "a" ] }';
/// var body = {
/// type: "hash",
/// unique: false,
/// sparse: true,
/// fields: [ "a" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -556,7 +567,11 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "skiplist", "unique" : false, "fields" : [ "a", "b" ] }';
/// var body = {
/// type: "skiplist",
/// unique: false,
/// fields: [ "a", "b" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -573,7 +588,12 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type": "skiplist", "unique" : false, "sparse" : true, "fields" : [ "a" ] }';
/// var body = {
/// type: "skiplist",
/// unique: false,
/// sparse: true,
/// fields: [ "a" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -636,7 +656,10 @@ function get_api_index (req, res) {
/// db._create(cn);
///
/// var url = "/_api/index?collection=" + cn;
/// var body = '{ "type" : "fulltext", "fields" : [ "text" ] }';
/// var body = {
/// type: "fulltext",
/// fields: [ "text" ]
/// };
///
/// var response = logCurlRequest('POST', url, body);
///
@ -687,6 +710,7 @@ function get_api_index (req, res) {
///
/// **Note**: The following index types do not support uniqueness, and using
/// the *unique* attribute with these types may lead to an error:
///
/// - cap constraints
/// - fulltext indexes
///
@ -742,20 +766,9 @@ function post_api_index (req, res) {
body.collection = name;
}
// fill "unique" attribute from "constraint" attribute to be downward-compatible
// with old geo index API
if (body.hasOwnProperty("constraint") && ! body.hasOwnProperty("unique")) {
body.unique = body.constraint;
}
// create the index
var index = collection.ensureIndex(body);
if (index.isNewlyCreated) {
actions.resultOk(req, res, actions.HTTP_CREATED, index);
}
else {
actions.resultOk(req, res, actions.HTTP_OK, index);
}
actions.resultOk(req, res, index.isNewlyCreated ? actions.HTTP_CREATED : actions.HTTP_OK, index);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -709,23 +709,21 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
body = {
type : "geo",
fields : [ lat ],
geoJson : lon,
constraint : false
geoJson : lon
};
}
else if (lon === undefined) {
body = {
type : "geo",
fields : [ lat ],
geoJson : false,
constraint : false
geoJson : false
};
}
else {
body = {
type : "geo",
fields : [ lat, lon ],
constraint : false
geoJson: false
};
}
@ -738,55 +736,11 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
////////////////////////////////////////////////////////////////////////////////
/// @brief ensures a geo constraint
/// since ArangoDB 2.5, this is just a redirection to ensureGeoIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) {
var body;
// only two parameter
if (ignoreNull === undefined) {
ignoreNull = lon;
if (typeof ignoreNull !== "boolean") {
throw "usage: ensureGeoConstraint(<lat>, <lon>, <ignore-null>)"
+ " or ensureGeoConstraint(<lat>, <geo-json>, <ignore-null>)";
}
body = {
type : "geo",
fields : [ lat ],
geoJson : false,
constraint : true,
ignoreNull : ignoreNull
};
}
// three parameter
else {
if (typeof lon === "boolean") {
body = {
type : "geo",
fields : [ lat ],
geoJson : lon,
constraint : true,
ignoreNull : ignoreNull
};
}
else {
body = {
type : "geo",
fields : [ lat, lon ],
constraint : true,
ignoreNull : ignoreNull
};
}
}
var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body));
arangosh.checkRequestResult(requestResult);
return requestResult;
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon) {
return this.ensureGeoIndex(lat, lon);
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -708,23 +708,21 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
body = {
type : "geo",
fields : [ lat ],
geoJson : lon,
constraint : false
geoJson : lon
};
}
else if (lon === undefined) {
body = {
type : "geo",
fields : [ lat ],
geoJson : false,
constraint : false
geoJson : false
};
}
else {
body = {
type : "geo",
fields : [ lat, lon ],
constraint : false
geoJson: false
};
}
@ -737,55 +735,11 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
////////////////////////////////////////////////////////////////////////////////
/// @brief ensures a geo constraint
/// since ArangoDB 2.5, this is just a redirection to ensureGeoIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) {
var body;
// only two parameter
if (ignoreNull === undefined) {
ignoreNull = lon;
if (typeof ignoreNull !== "boolean") {
throw "usage: ensureGeoConstraint(<lat>, <lon>, <ignore-null>)"
+ " or ensureGeoConstraint(<lat>, <geo-json>, <ignore-null>)";
}
body = {
type : "geo",
fields : [ lat ],
geoJson : false,
constraint : true,
ignoreNull : ignoreNull
};
}
// three parameter
else {
if (typeof lon === "boolean") {
body = {
type : "geo",
fields : [ lat ],
geoJson : lon,
constraint : true,
ignoreNull : ignoreNull
};
}
else {
body = {
type : "geo",
fields : [ lat, lon ],
constraint : true,
ignoreNull : ignoreNull
};
}
}
var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body));
arangosh.checkRequestResult(requestResult);
return requestResult;
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon) {
return this.ensureGeoIndex(lat, lon);
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -547,7 +547,8 @@ function ensureIndexSuite() {
assertEqual("geo1", idx.type);
assertFalse(idx.unique);
assertEqual([ "a" ], idx.fields);
assertFalse(idx.ignoreNull);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
res = collection.getIndexes()[collection.getIndexes().length - 1];
@ -555,7 +556,8 @@ function ensureIndexSuite() {
assertEqual("geo1", res.type);
assertFalse(res.unique);
assertEqual([ "a" ], res.fields);
assertFalse(res.ignoreNull);
assertTrue(res.ignoreNull);
assertTrue(res.sparse);
assertFalse(res.geoJson);
assertEqual(idx.id, res.id);
@ -572,17 +574,19 @@ function ensureIndexSuite() {
var idx = collection.ensureIndex({ type: "geo2", fields: [ "a", "b" ], unique: true });
assertEqual("geo2", idx.type);
assertTrue(idx.unique);
assertFalse(idx.unique);
assertEqual([ "a", "b" ], idx.fields);
assertFalse(idx.ignoreNull);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
res = collection.getIndexes()[collection.getIndexes().length - 1];
assertEqual("geo2", res.type);
assertTrue(res.unique);
assertFalse(res.unique);
assertEqual([ "a", "b" ], res.fields);
assertFalse(res.ignoreNull);
assertTrue(res.ignoreNull);
assertTrue(res.ignoreNull);
assertFalse(res.geoJson);
assertEqual(idx.id, res.id);

View File

@ -198,8 +198,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -208,8 +209,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -218,8 +220,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -230,8 +233,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -247,8 +251,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -257,8 +262,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -267,8 +273,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -279,8 +286,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -296,8 +304,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -305,8 +314,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -316,8 +326,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertFalse(idx.isNewlyCreated);
},
@ -332,9 +343,10 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertFalse(idx.geoJson);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -342,40 +354,22 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertTrue(idx.ignoreNull);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
idx = collection.ensureGeoConstraint("loc", true, true);
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
assertFalse(idx.isNewlyCreated);
collection.unload();
idx = collection.ensureGeoConstraint("loc", true, true);
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
idx = collection.ensureGeoConstraint("loc", false);
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -386,8 +380,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -403,8 +398,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -413,8 +409,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertTrue(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -423,8 +420,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -435,8 +433,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(id, idx.id);
assertEqual("geo1", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertFalse(idx.geoJson);
assertEqual(["loc"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -452,8 +451,9 @@ function GeoIndexCreationSuite() {
assertNotEqual(0, id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertTrue(idx.isNewlyCreated);
@ -461,8 +461,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertFalse(idx.isNewlyCreated);
@ -472,28 +473,9 @@ function GeoIndexCreationSuite() {
assertEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.constraint);
assertTrue(idx.ignoreNull);
assertEqual(["lat", "lon"], idx.fields);
assertFalse(idx.isNewlyCreated);
idx = collection.ensureGeoConstraint("lat", "lon", false);
assertNotEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertEqual(["lat", "lon"], idx.fields);
assertTrue(idx.isNewlyCreated);
collection.unload();
idx = collection.ensureGeoConstraint("lat", "lon", false);
assertNotEqual(id, idx.id);
assertEqual("geo2", idx.type);
assertTrue(idx.constraint);
assertFalse(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual(["lat", "lon"], idx.fields);
assertFalse(idx.isNewlyCreated);
}
@ -562,300 +544,8 @@ function GeoIndexErrorHandlingSuite() {
collection.replace(d4, { loc : [ -100, -200 ] });
assertEqual(1, collection.near(0,0).toArray().length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: error handling index
////////////////////////////////////////////////////////////////////////////////
testErrorHandlingConstraintList : function () {
collection.ensureGeoConstraint("loc", false);
var d1 = collection.save({ loc : [ 0, 0 ] });
try {
collection.save({ a : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ loc : null });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ loc : [0] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ loc : [ -100, -200 ] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
try {
collection.replace(d1._id, { a : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : null });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : [0] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : [ -100, -200 ] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: error handling index
////////////////////////////////////////////////////////////////////////////////
testErrorHandlingConstraintNullList : function () {
collection.ensureGeoConstraint("loc", true);
var d1 = collection.save({ loc : [ 0, 0 ] });
collection.save({ a : 1 });
collection.save({ loc : null });
try {
collection.save({ loc : [0] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ loc : [ -100, -200 ] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
collection.replace(d1._id, { a : 1 });
collection.replace(d1._id, { loc : null });
try {
collection.replace(d1._id, { loc : [0] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : [ -100, -200 ] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : [ -100, null ] });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { loc : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(0, collection.near(0,0).toArray().length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: error handling index
////////////////////////////////////////////////////////////////////////////////
testErrorHandlingConstraintAttribute : function () {
collection.ensureGeoConstraint("lat", "lon", false);
var d1 = collection.save({ lat : 0, lon : 0 });
try {
collection.save({ a : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ lat : null, lon : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ lat : 0 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ lat : -100, lon : -200 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
try {
collection.replace(d1._id, { a : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : null, lon : 1 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : 0 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : -100, lon : -200 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: error handling index
////////////////////////////////////////////////////////////////////////////////
testErrorHandlingConstraintNullList2 : function () {
collection.ensureGeoConstraint("lat", "lon", true);
var d1 = collection.save({ lat : 0, lon : 0 });
collection.save({ a : 1 });
collection.save({ lat : null, lon : 1 });
collection.save({ lat : 1, lon : null });
try {
collection.save({ lat : "Hello", lon : 10 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.save({ lat : -100, lon : -200 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(1, collection.near(0,0).toArray().length);
collection.replace(d1._id, { a : 1 });
collection.replace(d1._id, { lat : null });
try {
collection.replace(d1._id, { lat : "Hello" });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : -100, lon : -200 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : -100, lon : "Hello" });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
try {
collection.replace(d1._id, { lat : "Hello", lon : 10 });
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_ARANGO_GEO_INDEX_VIOLATED.code, err.errorNum);
}
assertEqual(0, collection.near(0,0).toArray().length);
}
};
}

View File

@ -643,8 +643,9 @@ function getIndexesEdgesSuite() {
var idx = res[2];
assertEqual("geo2", idx.type);
assertTrue(idx.unique);
assertFalse(idx.ignoreNull);
assertFalse(idx.unique);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual([ "lat", "lon" ], idx.fields);
assertTrue(idx.hasOwnProperty("id"));
assertEqual(collection.name(), idx.id.substr(0, collection.name().length));
@ -663,8 +664,9 @@ function getIndexesEdgesSuite() {
var idx = res[2];
assertEqual("geo2", idx.type);
assertTrue(idx.unique);
assertFalse(idx.unique);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual([ "lat", "lon" ], idx.fields);
assertTrue(idx.hasOwnProperty("id"));
assertEqual(collection.name(), idx.id.substr(0, collection.name().length));
@ -683,9 +685,10 @@ function getIndexesEdgesSuite() {
var idx = res[2];
assertEqual("geo1", idx.type);
assertTrue(idx.unique);
assertFalse(idx.unique);
assertTrue(idx.geoJson);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual([ "lat" ], idx.fields);
assertTrue(idx.hasOwnProperty("id"));
assertEqual(collection.name(), idx.id.substr(0, collection.name().length));
@ -706,7 +709,8 @@ function getIndexesEdgesSuite() {
assertEqual("geo1", idx.type);
assertFalse(idx.unique);
assertTrue(idx.geoJson);
assertFalse(idx.ignoreNull);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual([ "lat" ], idx.fields);
assertTrue(idx.hasOwnProperty("id"));
assertEqual(collection.name(), idx.id.substr(0, collection.name().length));
@ -726,7 +730,8 @@ function getIndexesEdgesSuite() {
assertEqual("geo2", idx.type);
assertFalse(idx.unique);
assertFalse(idx.ignoreNull);
assertTrue(idx.ignoreNull);
assertTrue(idx.sparse);
assertEqual([ "lat", "lon" ], idx.fields);
assertTrue(idx.hasOwnProperty("id"));
assertEqual(collection.name(), idx.id.substr(0, collection.name().length));

View File

@ -1201,6 +1201,10 @@ ArangoCollection.prototype.ensureHashIndex = function () {
/// All documents which do not have the attribute paths or which values
/// are not suitable, are ignored.
///
/// Geo indexes are always sparse, meaning that documents with do not contain
/// the index attributes or have non-numeric values in the index attributes
/// will not be indexed.
///
/// In case that the index was successfully created, an object with the index
/// details, including the index-identifier, is returned.
///
@ -1248,57 +1252,23 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
////////////////////////////////////////////////////////////////////////////////
/// @brief ensures that a geo constraint exists
/// @startDocuBlock collectionEnsureGeoConstraint
/// `collection.ensureGeoConstraint(location, ignore-null)`
/// `collection.ensureGeoConstraint(location)`
///
/// `collection.ensureGeoConstraint(location, true, ignore-null)`
/// `collection.ensureGeoConstraint(location, true)`
///
/// `collection.ensureGeoConstraint(latitude, longitude, ignore-null)`
/// `collection.ensureGeoConstraint(latitude, longitude)`
///
/// Works like *ensureGeoIndex* but requires that the documents contain
/// a valid geo definition. If *ignore-null* is true, then documents with
/// a null in *location* or at least one null in *latitude* or
/// *longitude* are ignored.
/// Since ArangoDB 2.5, this method is an alias for *ensureGeoIndex* since
/// geo indexes are always sparse, meaning that documents that do not contain
/// the index attributes or have non-numeric values in the index attributes
/// will not be indexed.
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) {
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon) {
"use strict";
// only two parameter
if (ignoreNull === undefined) {
ignoreNull = lon;
if (typeof ignoreNull !== "boolean") {
throw "usage: ensureGeoConstraint(<lat>, <lon>, <ignore-null>)"
+ " or ensureGeoConstraint(<lat>, <geo-json>, <ignore-null>)";
}
return this.ensureIndex({
type : "geo1",
fields : [ lat ],
geoJson : false,
unique : true,
ignoreNull : ignoreNull
});
}
// three parameter
if (typeof lon === "boolean") {
return this.ensureIndex({
type : "geo1",
fields : [ lat ],
geoJson : lon,
unique : true,
ignoreNull : ignoreNull
});
}
return this.ensureIndex({
type : "geo2",
fields : [ lat, lon ],
unique : true,
ignoreNull : ignoreNull
});
return this.ensureGeoIndex(lat, lon);
};
////////////////////////////////////////////////////////////////////////////////