Skip to content

PCBC-967 Support for vector search #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Couchbase/Cluster.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,23 @@ public function searchQuery(string $indexName, SearchQuery $query, SearchOptions
return new SearchResult($result);
}

public function search(string $indexName, SearchRequest $request, SearchOptions $options = null): SearchResult
{
$exportedRequest = SearchRequest::export($request);
$exportedOptions = SearchOptions::export($options);
$exportedOptions["showRequest"] = false;
$query = $exportedRequest['searchQuery'];

if (!$exportedRequest['vectorSearch']) {
$result = Extension\searchQuery($this->core, $indexName, json_encode($query), $exportedOptions);
return new SearchResult($result);
}

$vectorSearch = $exportedRequest['vectorSearch'];
$result = Extension\vectorSearch($this->core, $indexName, json_encode($query), json_encode($vectorSearch), $exportedOptions, VectorSearchOptions::export($vectorSearch->options()));
return new SearchResult($result);
}

/**
* Creates a new bucket manager object for managing buckets.
*
Expand Down
1 change: 1 addition & 0 deletions Couchbase/SearchOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ public static function export(?SearchOptions $options): array
'highlightFields' => $highlightFields,
'collections' => $options->collectionNames,
'includeLocations' => $options->includeLocations,
'showRequest' => null,
];
}
}
132 changes: 132 additions & 0 deletions Couchbase/SearchRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

/**
* Copyright 2014-Present Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Couchbase;

use Couchbase\Exception\InvalidArgumentException;

class SearchRequest
{
private ?SearchQuery $searchQuery = null;
private ?VectorSearch $vectorSearch = null;

/**
* Constructs a SearchRequest.
*
* Use {@link SearchRequest::searchQuery()} or {@link SearchRequest::vectorSearch()} to combine a SearchQuery
* with a VectorQuery.
*
* @param SearchQuery|VectorSearch $searchQueryOrVectorSearch
*
* @since 4.1.7
*
* @VOLATILE: This API is subject to change at any time.
*/
public function __construct(SearchQuery|VectorSearch $searchQueryOrVectorSearch)
{
if ($searchQueryOrVectorSearch instanceof SearchQuery) {
$this->searchQuery = $searchQueryOrVectorSearch;
} else {
$this->vectorSearch = $searchQueryOrVectorSearch;
}
}

/**
* Static builder to keep code more readable.
*
* Use {@link SearchRequest::searchQuery()} or {@link SearchRequest::vectorSearch()} to combine a SearchQuery
* with a VectorQuery.
*
* @param SearchQuery|VectorSearch $searchQueryOrVectorSearch
*
* @since 4.1.7
* @return SearchRequest
*
* @VOLATILE: This API is subject to change at any time.
*/
public static function build(SearchQuery|VectorSearch $searchQueryOrVectorSearch): SearchRequest
{
return new SearchRequest($searchQueryOrVectorSearch);
}

/**
* Sets a SearchQuery in the SearchRequest, if one is not already set.
*
* @param SearchQuery $searchQuery
*
* @since 4.1.7
* @return SearchRequest
*
* @throws InvalidArgumentException
*
* @VOLATILE: This API is subject to change at any time.
*/
public function searchQuery(SearchQuery $searchQuery): SearchRequest
{
if ($this->searchQuery != null) {
throw new InvalidArgumentException("There can only be one SearchQuery in a SearchRequest");
}
$this->searchQuery = $searchQuery;
return $this;
}

/**
* Sets a VectorSearch in the SearchRequest, if one is not already set.
*
* @param VectorSearch $vectorSearch
*
* @since 4.1.7
* @return SearchRequest
*
* @throws InvalidArgumentException
*
* @VOLATILE: This API is subject to change at any time.
*/
public function vectorSearch(VectorSearch $vectorSearch): SearchRequest
{
if ($this->vectorSearch != null) {
throw new InvalidArgumentException("There can only be one VectorSearch in a SearchRequest");
}
$this->vectorSearch = $vectorSearch;
return $this;
}

/**
* @internal
*
* @param SearchRequest $request
*
* @return array
* @since 4.1.7
*
* @throws InvalidArgumentException
*/
public static function export(SearchRequest $request): array
{
if ($request->searchQuery == null) {
$request->searchQuery(new MatchNoneSearchQuery());
}

return [
'searchQuery' => $request->searchQuery,
'vectorSearch' => $request->vectorSearch,
];
}
}
133 changes: 133 additions & 0 deletions Couchbase/VectorQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

/**
* Copyright 2014-Present Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Couchbase;

use Couchbase\Exception\InvalidArgumentException;

class VectorQuery
{
private string $vectorFieldName;
private array $vectorQuery;
private int $numCandidates;
private ?float $boost = null;

/**
* @param string $vectorFieldName the document field that contains the vector
* @param array $vectorQuery the vector query to run. Cannot be empty.
*
* @since 4.1.7
*
* @throws InvalidArgumentException
*
* @VOLATILE: This API is subject to change at any time.
*/
public function __construct(string $vectorFieldName, array $vectorQuery)
{
if (empty($vectorQuery)) {
throw new InvalidArgumentException("The vectorQuery cannot be empty");
}
$this->vectorFieldName = $vectorFieldName;
$this->vectorQuery = $vectorQuery;
$this->numCandidates = 3;
}

/**
* Static helper to keep code more readable
*
* @param string $vectorFieldName the document field that contains the vector
* @param array $vectorQuery the vector query to run. Cannot be empty.
*
* @since 4.1.7
* @return VectorQuery
*
* @throws InvalidArgumentException
*
* @VOLATILE: This API is subject to change at any time.
*/
static function build(string $vectorFieldName, array $vectorQuery): VectorQuery
{
return new VectorQuery($vectorFieldName, $vectorQuery);
}

/**
* Sets the number of results that will be returned from this vector query. Defaults to 3.
*
* @param int|null $numCandidates the number of results returned.
*
* @since 4.1.7
* @return VectorQuery
*
* @throws InvalidArgumentException
*
* @VOLATILE: This API is subject to change at any time.
*/
public function numCandidates(int $numCandidates): VectorQuery
{
if ($numCandidates < 1) {
throw new InvalidArgumentException("The numCandidates cannot be less than 1");
}
$this->numCandidates = $numCandidates;
return $this;
}

/**
* Sets the boost for this query.
*
* @param float $boost the boost value to use.
*
* @return VectorQuery
* @since 4.1.7
*
* @VOLATILE: This API is subject to change at any time.
*/
public function boost(float $boost): VectorQuery
{
$this->boost = $boost;
return $this;
}

/**
* @internal
*
* @param VectorQuery $query
*
* @return array
* @since 4.1.7
*/
public static function export(VectorQuery $query): array
{
$json = [
'field' => $query->vectorFieldName,
];

if ($query->boost != null) {
$json['boost'] = $query->boost;
}

$vectorQueries = [];
foreach ($query->vectorQuery as $value) {
$vectorQueries[] = $value;
}
$json['vector'] = $vectorQueries;
$json['k'] = $query->numCandidates;
return $json;
}
}
30 changes: 30 additions & 0 deletions Couchbase/VectorQueryCombination.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright 2014-Present Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

declare(strict_types=1);

namespace Couchbase;

/**
* Interface for setting how multiple vector queries are combined.
*/
interface VectorQueryCombination
{
public const AND = "and";
public const OR = "or";
}
Loading