Skip to content
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

Python FT.DROPINDEX command #2437

Merged
merged 14 commits into from
Oct 15, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#### Changes
* Python: Python FT.DROPINDEX command ([#2437](https://github.com/valkey-io/valkey-glide/pull/2437))
* Python: Python: Added FT.CREATE command([#2413](https://github.com/valkey-io/valkey-glide/pull/2413))
* Python: Add JSON.ARRLEN command ([#2403](https://github.com/valkey-io/valkey-glide/pull/2403))
* Python: Add JSON.CLEAR command ([#2418](https://github.com/valkey-io/valkey-glide/pull/2418))
Expand Down
30 changes: 26 additions & 4 deletions python/python/glide/async_commands/server_modules/ft.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from typing import List, Optional, cast

from glide.async_commands.server_modules.ft_constants import (
from glide.async_commands.server_modules.ft_options.ft_constants import (
CommandNames,
FtCreateKeywords,
)
Expand All @@ -30,10 +30,10 @@ async def create(
client (TGlideClient): The client to execute the command.
indexName (TEncodable): The index name for the index to be created
schema (List[Field]): The fields of the index schema, specifying the fields and their types.
options (Optional[FtCreateOptions]): Optional arguments for the [FT.CREATE] command.
options (Optional[FtCreateOptions]): Optional arguments for the FT.CREATE command. See `FtCreateOptions`.

Returns:
If the index is successfully created, returns "OK".
TOK: A simple "OK" response.

Examples:
>>> from glide.async_commands.server_modules import ft
Expand All @@ -44,7 +44,7 @@ async def create(
>>> prefixes.append("blog:post:")
>>> index = "idx"
>>> result = await ft.create(glide_client, index, schema, FtCreateOptions(DataType.HASH, prefixes))
b'OK' # Indicates successful creation of index named 'idx'
'OK' # Indicates successful creation of index named 'idx'
"""
args: List[TEncodable] = [CommandNames.FT_CREATE, indexName]
if options:
Expand All @@ -54,3 +54,25 @@ async def create(
for field in schema:
args.extend(field.toArgs())
return cast(TOK, await client.custom_command(args))


async def dropindex(client: TGlideClient, indexName: TEncodable) -> TOK:
"""
Drops an index. The index definition and associated content are deleted. Keys are unaffected.

Args:
client (TGlideClient): The client to execute the command.
indexName (TEncodable): The index name for the index to be dropped.

Returns:
TOK: A simple "OK" response.

Examples:
For the following example to work, an index named 'idx' must be already created. If not created, you will get an error.
>>> from glide.async_commands.server_modules import ft
>>> indexName = "idx"
>>> result = await ft.dropindex(glide_client, indexName)
'OK' # Indicates successful deletion/dropping of index named 'idx'
"""
args: List[TEncodable] = [CommandNames.FT_DROPINDEX, indexName]
return cast(TOK, await client.custom_command(args))
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ class CommandNames:
"""

FT_CREATE = "FT.CREATE"
FT_DROPINDEX = "FT.DROPINDEX"


class FtCreateKeywords:
"""
Keywords used in the [FT.CREATE] command statment.
Keywords used in the FT.CREATE command statment.
"""

SCHEMA = "SCHEMA"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from enum import Enum
from typing import List, Optional

from glide.async_commands.server_modules.ft_constants import FtCreateKeywords
from glide.async_commands.server_modules.ft_options.ft_constants import FtCreateKeywords
from glide.constants import TEncodable


Expand Down Expand Up @@ -85,15 +85,15 @@ def __init__(
self,
name: TEncodable,
type: FieldType,
alias: Optional[str] = None,
alias: Optional[TEncodable] = None,
):
"""
Initialize a new field instance.

Args:
name (TEncodable): The name of the field.
type (FieldType): The type of the field.
alias (Optional[str]): An alias for the field.
type (FieldType): The type of the field. See `FieldType`.
alias (Optional[TEncodable]): An alias for the field.
"""
self.name = name
self.type = type
Expand All @@ -119,13 +119,13 @@ class TextField(Field):
Class for defining text fields in a schema.
"""

def __init__(self, name: TEncodable, alias: Optional[str] = None):
def __init__(self, name: TEncodable, alias: Optional[TEncodable] = None):
"""
Initialize a new TextField instance.

Args:
name (TEncodable): The name of the text field.
alias (Optional[str]): An alias for the field.
alias (Optional[TEncodable]): An alias for the field.
"""
super().__init__(name, FieldType.TEXT, alias)

Expand All @@ -148,17 +148,17 @@ class TagField(Field):
def __init__(
self,
name: TEncodable,
alias: Optional[str] = None,
separator: Optional[str] = None,
alias: Optional[TEncodable] = None,
separator: Optional[TEncodable] = None,
case_sensitive: bool = False,
):
"""
Initialize a new TagField instance.

Args:
name (TEncodable): The name of the tag field.
alias (Optional[str]): An alias for the field.
separator (Optional[str]): Specify how text in the attribute is split into individual tags. Must be a single character.
alias (Optional[TEncodable]): An alias for the field.
separator (Optional[TEncodable]): Specify how text in the attribute is split into individual tags. Must be a single character.
case_sensitive (bool): Preserve the original letter cases of tags. If set to False, characters are converted to lowercase by default.
"""
super().__init__(name, FieldType.TAG, alias)
Expand All @@ -185,13 +185,13 @@ class NumericField(Field):
Class for defining the numeric fields in a schema.
"""

def __init__(self, name: TEncodable, alias: Optional[str] = None):
def __init__(self, name: TEncodable, alias: Optional[TEncodable] = None):
"""
Initialize a new NumericField instance.

Args:
name (TEncodable): The name of the numeric field.
alias (Optional[str]): An alias for the field.
alias (Optional[TEncodable]): An alias for the field.
"""
super().__init__(name, FieldType.NUMERIC, alias)

Expand Down Expand Up @@ -219,21 +219,21 @@ def __init__(self, dim: int, distance_metric: DistanceMetricType, type: VectorTy
Args:
dim (int): Number of dimensions in the vector.
distance_metric (DistanceMetricType): The distance metric used in vector type field. Can be one of [L2 | IP | COSINE].
type (VectorType): Vector type. The only supported type is FLOAT32.
type (VectorType): Vector type. The only supported type is FLOAT32. See `VectorType`.
"""
self.dim = dim
self.distance_metric = distance_metric
self.type = type

@abstractmethod
def toArgs(self) -> List[str]:
def toArgs(self) -> List[TEncodable]:
"""
Get the arguments to be used for the algorithm of the vector field.

Returns:
List[str]: A list of arguments.
List[TEncodable]: A list of arguments.
"""
args = []
args: List[TEncodable] = []
if self.dim:
args.extend([FtCreateKeywords.DIM, str(self.dim)])
if self.distance_metric:
Expand All @@ -260,19 +260,19 @@ def __init__(

Args:
dim (int): Number of dimensions in the vector.
distance_metric (DistanceMetricType): The distance metric used in vector type field. Can be one of [L2 | IP | COSINE].
type (VectorType): Vector type. The only supported type is FLOAT32.
distance_metric (DistanceMetricType): The distance metric used in vector type field. Can be one of [L2 | IP | COSINE]. See `DistanceMetricType`.
type (VectorType): Vector type. The only supported type is FLOAT32. See `VectorType`.
initial_cap (Optional[int]): Initial vector capacity in the index affecting memory allocation size of the index. Defaults to 1024.
"""
super().__init__(dim, distance_metric, type)
self.initial_cap = initial_cap

def toArgs(self) -> List[str]:
def toArgs(self) -> List[TEncodable]:
"""
Get the arguments representing the vector field created with FLAT algorithm.

Returns:
List[str]: A list of FLAT algorithm type vector arguments.
List[TEncodable]: A list of FLAT algorithm type vector arguments.
"""
args = super().toArgs()
if self.initial_cap:
Expand Down Expand Up @@ -300,8 +300,8 @@ def __init__(

Args:
dim (int): Number of dimensions in the vector.
distance_metric (DistanceMetricType): The distance metric used in vector type field. Can be one of [L2 | IP | COSINE].
type (VectorType): Vector type. The only supported type is FLOAT32.
distance_metric (DistanceMetricType): The distance metric used in vector type field. Can be one of [L2 | IP | COSINE]. See `DistanceMetricType`.
type (VectorType): Vector type. The only supported type is FLOAT32. See `VectorType`.
initial_cap (Optional[int]): Initial vector capacity in the index affecting memory allocation size of the index. Defaults to 1024.
m (Optional[int]): Number of maximum allowed outgoing edges for each node in the graph in each layer. Default is 16, maximum is 512.
ef_contruction (Optional[int]): Controls the number of vectors examined during index construction. Default value is 200, Maximum value is 4096.
Expand All @@ -313,12 +313,12 @@ def __init__(
self.ef_contruction = ef_contruction
self.ef_runtime = ef_runtime

def toArgs(self) -> List[str]:
def toArgs(self) -> List[TEncodable]:
"""
Get the arguments representing the vector field created with HSNW algorithm.

Returns:
List[str]: A list of HNSW algorithm type vector arguments.
List[TEncodable]: A list of HNSW algorithm type vector arguments.
"""
args = super().toArgs()
if self.initial_cap:
Expand All @@ -342,16 +342,16 @@ def __init__(
name: TEncodable,
algorithm: VectorAlgorithm,
attributes: VectorFieldAttributes,
alias: Optional[str] = None,
alias: Optional[TEncodable] = None,
):
"""
Initialize a new VectorField instance.

Args:
name (TEncodable): The name of the vector field.
algorithm (VectorAlgorithm): The vector indexing algorithm.
alias (Optional[str]): An alias for the field.
attributes (VectorFieldAttributes): Additional attributes to be passed with the vector field after the algorithm name.
algorithm (VectorAlgorithm): The vector indexing algorithm. See `VectorAlgorithm`.
alias (Optional[TEncodable]): An alias for the field.
attributes (VectorFieldAttributes): Additional attributes to be passed with the vector field after the algorithm name. See `VectorFieldAttributes`.
"""
super().__init__(name, FieldType.VECTOR, alias)
self.algorithm = algorithm
Expand Down Expand Up @@ -390,34 +390,34 @@ class DataType(Enum):

class FtCreateOptions:
"""
This class represents the input options to be used in the [FT.CREATE] command.
All fields in this class are optional inputs for [FT.CREATE].
This class represents the input options to be used in the FT.CREATE command.
All fields in this class are optional inputs for FT.CREATE.
"""

def __init__(
self,
data_type: Optional[DataType] = None,
prefixes: Optional[List[str]] = None,
prefixes: Optional[List[TEncodable]] = None,
):
"""
Initialize the [FT.CREATE] optional fields.
Initialize the FT.CREATE optional fields.

Args:
data_type (Optional[DataType]): The type of data to be indexed using [FT.CREATE].
prefixes (Optional[List[str]]): The prefix of the key to be indexed.
data_type (Optional[DataType]): The type of data to be indexed using FT.CREATE. See `DataType`.
prefixes (Optional[List[TEncodable]]): The prefix of the key to be indexed.
"""
self.data_type = data_type
self.prefixes = prefixes

def toArgs(self) -> List[str]:
def toArgs(self) -> List[TEncodable]:
"""
Get the optional arguments for the [FT.CREATE] command.
Get the optional arguments for the FT.CREATE command.

Returns:
List[str]:
List of [FT.CREATE] optional agruments.
List[TEncodable]:
List of FT.CREATE optional agruments.
"""
args = []
args: List[TEncodable] = []
if self.data_type:
args.append(FtCreateKeywords.ON)
args.append(self.data_type.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
VectorType,
)
from glide.config import ProtocolVersion
from glide.constants import OK
from glide.constants import OK, TEncodable
from glide.glide_client import GlideClusterClient


@pytest.mark.asyncio
class TestVss:
class TestFtCreate:
@pytest.mark.parametrize("cluster_mode", [True])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_vss_create(self, glide_client: GlideClusterClient):
async def test_ft_create(self, glide_client: GlideClusterClient):
fields: List[Field] = []
textFieldTitle: TextField = TextField("$title")
numberField: NumericField = NumericField("$published_at")
Expand All @@ -34,7 +34,7 @@ async def test_vss_create(self, glide_client: GlideClusterClient):
fields.append(numberField)
fields.append(textFieldCategory)

prefixes: List[str] = []
prefixes: List[TEncodable] = []
prefixes.append("blog:post:")

# Create an index with multiple fields with Hash data type.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import uuid
from typing import List

import pytest
from glide.async_commands.server_modules import ft
from glide.async_commands.server_modules.ft_options.ft_create_options import (
DataType,
Field,
FtCreateOptions,
TextField,
)
from glide.config import ProtocolVersion
from glide.constants import OK, TEncodable
from glide.exceptions import RequestError
from glide.glide_client import GlideClusterClient


@pytest.mark.asyncio
class TestFtDropIndex:
@pytest.mark.parametrize("cluster_mode", [True])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_ft_dropindex(self, glide_client: GlideClusterClient):
# Index name for the index to be dropped.
indexName = str(uuid.uuid4())
prateek-kumar-improving marked this conversation as resolved.
Show resolved Hide resolved

fields: List[Field] = []
textFieldTitle: TextField = TextField("$title")
fields.append(textFieldTitle)
prefixes: List[TEncodable] = []
prefixes.append("blog:post:")

# Create an index with multiple fields with Hash data type.
result = await ft.create(
glide_client, indexName, fields, FtCreateOptions(DataType.HASH, prefixes)
)
assert result == OK

# Drop the index. Expects "OK" as a response.
result = await ft.dropindex(glide_client, indexName)
assert result == OK

# Drop a non existent index. Expects a RequestError.
with pytest.raises(RequestError):
await ft.dropindex(glide_client, indexName)
Loading