diff --git a/Couchbase/Management/SearchIndex.php b/Couchbase/Management/SearchIndex.php index 03999ea4..e090569b 100644 --- a/Couchbase/Management/SearchIndex.php +++ b/Couchbase/Management/SearchIndex.php @@ -319,9 +319,9 @@ public function setPlanParams(string|array|stdClass $planParams): SearchIndex } /** - * @internal * @return array * + * @internal * @since 4.1.5 */ public function jsonSerialize(): array @@ -350,10 +350,10 @@ public function jsonSerialize(): array } /** - * @internal * @param array|stdClass $searchIndex * @return SearchIndex * + * @internal * @since 4.1.5 */ public static function import(array|stdClass $searchIndex): SearchIndex @@ -386,10 +386,10 @@ public static function import(array|stdClass $searchIndex): SearchIndex } /** - * @internal * @param SearchIndex $index * @return array * + * @internal * @since 4.1.5 */ public static function export(SearchIndex $index): array diff --git a/Couchbase/Management/SearchIndexManager.php b/Couchbase/Management/SearchIndexManager.php index 0ec87fa8..f9144a77 100644 --- a/Couchbase/Management/SearchIndexManager.php +++ b/Couchbase/Management/SearchIndexManager.php @@ -47,6 +47,8 @@ public function __construct($core) * @param GetSearchIndexOptions|null $options * @return SearchIndex * + * @throws Couchbase\Exception\IndexNotFoundException + * * @since 4.1.5 */ public function getIndex(string $indexName, GetSearchIndexOptions $options = null): SearchIndex diff --git a/tests/BucketManagerTest.php b/tests/BucketManagerTest.php index 590f244f..44f05f68 100644 --- a/tests/BucketManagerTest.php +++ b/tests/BucketManagerTest.php @@ -155,6 +155,8 @@ public function testCreateBucketNumReplicas() public function testCreateBucketReplicaIndexes() { + $this->skipIfReplicasAreNotConfigured(); + $settings = new BucketSettings($this->bucketName); $settings->setBucketType(BucketType::COUCHBASE)->enableReplicaIndexes(true); $this->manager->createBucket($settings); diff --git a/tests/Helpers/ServerVersion.php b/tests/Helpers/ServerVersion.php index 593eb2e8..1f746c7c 100644 --- a/tests/Helpers/ServerVersion.php +++ b/tests/Helpers/ServerVersion.php @@ -289,6 +289,11 @@ public function supportsScopeSearchIndexes(): bool return ($this->major == 7 && $this->minor >= 6) || $this->major > 7; } + public function supportsVectorSearch(): bool + { + return ($this->major == 7 && $this->minor >= 6) || $this->major > 7; + } + /** * @return int */ diff --git a/tests/QueryIndexManagerTest.php b/tests/QueryIndexManagerTest.php index 4fe4ee74..7eb5a79a 100644 --- a/tests/QueryIndexManagerTest.php +++ b/tests/QueryIndexManagerTest.php @@ -62,9 +62,9 @@ public function testQueryIndexesCrud() $manager->createPrimaryIndex($bucketName, CreateQueryPrimaryIndexOptions::build()->ignoreIfExists(true)); break; } catch (CouchbaseException $ex) { - printf("Error during primary index creation: %s, %s", $ex->getMessage(), var_export($ex->getContext(), true)); + printf("Error during primary index creation for '%s': %s, %s", $bucketName, $ex->getMessage(), var_export($ex->getContext(), true)); if (time() > $deadline) { - $this->assertFalse("timed out waiting for create index to succeed"); + $this->fail("timed out waiting for create index to succeed"); } sleep(1); } diff --git a/tests/SearchTest.php b/tests/SearchTest.php index 284c5487..1b5f8294 100644 --- a/tests/SearchTest.php +++ b/tests/SearchTest.php @@ -29,6 +29,8 @@ use Couchbase\Exception\IndexNotFoundException; use Couchbase\GeoBoundingBoxSearchQuery; use Couchbase\GeoDistanceSearchQuery; +use Couchbase\Management\SearchIndex; +use Couchbase\Management\SearchIndexManager; use Couchbase\MatchAllSearchQuery; use Couchbase\MatchNoneSearchQuery; use Couchbase\MatchPhraseSearchQuery; @@ -61,12 +63,36 @@ class SearchTest extends Helpers\CouchbaseTestCase { private ClusterInterface $cluster; + private SearchIndexManager $indexManager; public function setUp(): void { parent::setUp(); $this->cluster = $this->connectCluster(); + + if (self::env()->useCouchbase()) { + $this->indexManager = $this->cluster->searchIndexes(); + try { + $this->indexManager->getIndex("beer-search"); + } catch (IndexNotFoundException $ex) { + $indexDump = json_decode(file_get_contents(__DIR__ . "/beer-search.json"), true); + $index = SearchIndex::build("beer-search", "beer-sample"); + $index->setParams($indexDump["params"]); + $this->indexManager->upsertIndex($index); + } + while (true) { + try { + $indexedDocuments = $this->indexManager->getIndexedDocumentsCount("beer-search"); + fprintf(STDERR, "Indexing 'beer-search': %d docs\n", $indexedDocuments); + if ($indexedDocuments > 7000) { + break; + } + sleep(3); + } catch (\Couchbase\Exception\IndexNotReadyException $ex) { + } + } + } } public function tearDown(): void @@ -495,6 +521,7 @@ public function testBooleanSearchQuery() public function testVectorSearchThrowsIndexNotFound() { $this->skipIfCaves(); + $this->skipIfUnsupported($this->version()->supportsVectorSearch()); $vectorQueryOne = VectorQuery::build("foo", [0.32, -0.536, 0.842])->boost(0.5)->numCandidates(4); $vectorQueryTwo = VectorQuery::build("bar", [-0.00810353, 0.6433, 0.52364]); @@ -546,143 +573,3 @@ public function testScopeSearchThrowsFeatureNotAvailable() $this->openBucket()->defaultScope()->search("unknown-index", $searchRequest); } } - -/* -curl -XPUT -H "Content-Type: application/json" \ --u Administrator:password http://localhost:8094/api/index/beer-search -d \ -'{ - "type": "fulltext-index", - "name": "beer-search", - "sourceType": "couchbase", - "sourceName": "beer-sample", - "planParams": { - "maxPartitionsPerPIndex": 171, - "indexPartitions": 6 - }, - "params": { - "doc_config": { - "docid_prefix_delim": "", - "docid_regexp": "", - "mode": "type_field", - "type_field": "type" - }, - "mapping": { - "analysis": {}, - "default_analyzer": "standard", - "default_datetime_parser": "dateTimeOptional", - "default_field": "_all", - "default_mapping": { - "dynamic": true, - "enabled": true - }, - "default_type": "_default", - "docvalues_dynamic": true, - "index_dynamic": true, - "store_dynamic": false, - "type_field": "_type", - "types": { - "beer": { - "dynamic": true, - "enabled": true, - "properties": { - "abv": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "abv", - "store": true, - "type": "number" - } - ] - }, - "category": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "category", - "store": true, - "type": "text" - } - ] - }, - "description": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "description", - "store": true, - "type": "text" - } - ] - }, - "name": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "name", - "store": true, - "type": "text" - } - ] - }, - "style": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "style", - "store": true, - "type": "text" - } - ] - }, - "updated": { - "dynamic": false, - "enabled": true, - "fields": [ - { - "docvalues": true, - "include_in_all": true, - "include_term_vectors": true, - "index": true, - "name": "updated", - "store": true, - "type": "datetime" - } - ] - } - } - } - } - }, - "store": { - "indexType": "scorch" - } - }, - "sourceParams": {} -}' -*/ diff --git a/tests/beer-search.json b/tests/beer-search.json new file mode 100644 index 00000000..f666aeff --- /dev/null +++ b/tests/beer-search.json @@ -0,0 +1,135 @@ +{ + "type": "fulltext-index", + "name": "beer-search", + "sourceType": "couchbase", + "sourceName": "beer-sample", + "planParams": { + "maxPartitionsPerPIndex": 171, + "indexPartitions": 6 + }, + "params": { + "doc_config": { + "docid_prefix_delim": "", + "docid_regexp": "", + "mode": "type_field", + "type_field": "type" + }, + "mapping": { + "analysis": {}, + "default_analyzer": "standard", + "default_datetime_parser": "dateTimeOptional", + "default_field": "_all", + "default_mapping": { + "dynamic": true, + "enabled": true + }, + "default_type": "_default", + "docvalues_dynamic": true, + "index_dynamic": true, + "store_dynamic": false, + "type_field": "_type", + "types": { + "beer": { + "dynamic": true, + "enabled": true, + "properties": { + "abv": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "abv", + "store": true, + "type": "number" + } + ] + }, + "category": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "category", + "store": true, + "type": "text" + } + ] + }, + "description": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "description", + "store": true, + "type": "text" + } + ] + }, + "name": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "name", + "store": true, + "type": "text" + } + ] + }, + "style": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "style", + "store": true, + "type": "text" + } + ] + }, + "updated": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "docvalues": true, + "include_in_all": true, + "include_term_vectors": true, + "index": true, + "name": "updated", + "store": true, + "type": "datetime" + } + ] + } + } + } + } + }, + "store": { + "indexType": "scorch" + } + }, + "sourceParams": {} +}