redis-om
Version:
Object mapping, and more, for Redis and Node.js. Written in TypeScript.
1,326 lines (1,313 loc) • 52.2 kB
TypeScript
import { createClient, createCluster, RediSearchSchema, SearchOptions } from 'redis';
/** The Symbol used to access the entity ID of an {@link Entity}. */
declare const EntityId: unique symbol;
/** The Symbol used to access the keyname of an {@link Entity}. */
declare const EntityKeyName: unique symbol;
/** Defines the objects returned from calls to {@link Repository | repositories }. */
type Entity = EntityData & {
/** The unique ID of the {@link Entity}. Access using the {@link EntityId} Symbol. */
[EntityId]?: string;
/** The key the {@link Entity} is stored under inside of Redis. Access using the {@link EntityKeyName} Symbol. */
[EntityKeyName]?: string;
};
/** The free-form data associated with an {@link Entity}. */
type EntityData = {
[key: string]: EntityDataValue | EntityData | Array<EntityDataValue | EntityData>;
};
/** Valid types for values in an {@link Entity}. */
type EntityDataValue = string | number | boolean | Date | Point | null | undefined | Array<EntityDataValue | EntityData>;
/** Defines a point on the globe using longitude and latitude. */
type Point = {
/** The longitude of the point. */
longitude: number;
/** The latitude of the point. */
latitude: number;
};
/** Valid field types for a {@link FieldDefinition}. */
type FieldType = 'boolean' | 'date' | 'number' | 'number[]' | 'point' | 'string' | 'string[]' | 'text';
/** All configuration properties that any field might have, regardless of type. */
type AllFieldDefinition = {
/** The type of the field (i.e. string, number, boolean, etc.) */
type: FieldType;
/**
* The default field name in Redis is the property name defined in the
* {@link SchemaDefinition}. Overrides the field name for a Hash to this
* value or in the case of JSON documents, sets the JSONPath to this
* value preceded by `$.`. Overridden by {@link field} and/or {@link path}
* settings.
* @deprecated
*/
alias?: string;
/**
* Is this field indexed and thus searchable with Redis OM. Defaults
* to true.
*/
indexed?: boolean;
/**
* The field name used to store this in a Redis Hash. Defaults to the
* name used in the {@link SchemaDefinition} or the {@link alias}
* property.
*/
field?: string;
/**
* The JSONPath expression this field references. Used only by search
* and only for JSON documents. Defaults to the name used in the
* {@link SchemaDefinition} or the {@link alias} property prefixed
* with `$.` .
*/
path?: string;
/** Enables sorting by this field. */
sortable?: boolean;
/** Is the original case of this field indexed with Redis OM. Defaults to false. */
caseSensitive?: boolean;
/** Is this (sortable) field normalized when indexed. Defaults to true. */
normalized?: boolean;
/**
* Due to how RediSearch works, strings and arrays are sometimes stored the same in Redis, as a
* simple string. This is the separator used to split those strings when it is an array. If your
* StringField contains this separator, this can cause problems. You can change it here to avoid
* those problems. Defaults to `|`.
*/
separator?: string;
/**
* Enables setting the phonetic matcher to use, supported matchers are:
* dm:en - Double Metaphone for English
* dm:fr - Double Metaphone for French
* dm:pt - Double Metaphone for Portuguese
* dm:es - Double Metaphone for Spanish
*/
matcher?: 'dm:en' | 'dm:fr' | 'dm:pt' | 'dm:es';
/** Is word stemming applied to this field with Redis OM. Defaults to true. */
stemming?: boolean;
/** Enables setting the weight to apply to a text field */
weight?: number;
};
/** The configuration properties that all fields have in common. */
type CommonFieldDefinition = Pick<AllFieldDefinition, "type" | "alias" | "indexed" | "field" | "path">;
/** A field representing a boolean. */
type BooleanFieldDefinition = {
type: 'boolean';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable">;
/** A field representing a date/time. */
type DateFieldDefinition = {
type: 'date';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable">;
/** A field representing a number. */
type NumberFieldDefinition = {
type: 'number';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable">;
/** A field representing an array of numbers. */
type NumberArrayFieldDefinition = {
type: 'number[]';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable">;
/** A field representing a point on the globe. */
type PointFieldDefinition = {
type: 'point';
} & CommonFieldDefinition;
/** A field representing a whole string. */
type StringFieldDefinition = {
type: 'string';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable" | "caseSensitive" | "normalized" | "separator">;
/** A field representing an array of strings. */
type StringArrayFieldDefinition = {
type: 'string[]';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable" | "caseSensitive" | "normalized" | "separator">;
/** A field representing searchable text. */
type TextFieldDefinition = {
type: 'text';
} & CommonFieldDefinition & Pick<AllFieldDefinition, "sortable" | "normalized" | "matcher" | "stemming" | "weight">;
/** Contains instructions telling how to map a property on an {@link Entity} to Redis. */
type FieldDefinition = BooleanFieldDefinition | DateFieldDefinition | NumberFieldDefinition | NumberArrayFieldDefinition | PointFieldDefinition | StringFieldDefinition | StringArrayFieldDefinition | TextFieldDefinition;
/** Group of {@link FieldDefinition}s that define the schema for an {@link Entity}. */
type SchemaDefinition = Record<string, FieldDefinition>;
/**
* Describes a field in a {@link Schema}.
*/
declare class Field {
#private;
/**
* Creates a Field.
*
* @param name The name of the Field.
* @param definition The underlying {@link FieldDefinition}.
*/
constructor(name: string, definition: FieldDefinition);
/** The name of the field. */
get name(): string;
/** The {@link FieldType | type} of the field. */
get type(): FieldType;
/** The field name used to store this {@link Field} in a Hash. */
get hashField(): string;
/** The JSONPath used to store this {@link Field} in a JSON document. */
get jsonPath(): string;
/** The separator for string[] fields when stored in Hashes. */
get separator(): string;
/** Indicates that the field as sortable. */
get sortable(): boolean;
/** The case-sensitivity of the field. */
get caseSensitive(): boolean;
/** Indicates the field as being indexed—and thus queryable—by RediSearch. */
get indexed(): boolean;
/** Indicates that the field as indexed with stemming support. */
get stemming(): boolean;
/** Indicates that the field is normalized. Ignored if sortable is false. */
get normalized(): boolean;
/** The search weight of the field. */
get weight(): number | null;
/** The phonetic matcher for the field. */
get matcher(): string | null;
/** Is this type an array or not. */
get isArray(): boolean;
}
/** The type of data structure in Redis to map objects to. */
type DataStructure = 'HASH' | 'JSON';
/** A function that generates random entityIds. */
type IdStrategy = () => Promise<string>;
/** Valid values for how to use stop words for a given {@link Schema}. */
type StopWordOptions = 'OFF' | 'DEFAULT' | 'CUSTOM';
/** Configuration options for a {@link Schema}. */
type SchemaOptions = {
/**
* The name used by RediSearch to store the index for this {@link Schema}. Defaults
* to prefix followed by `:index`. So, for a prefix of `Foo`, it would use `Foo:index`.
*/
indexName?: string;
/**
* The name used by Redis OM to store the hash of the index for this {@link Schema}.
* Defaults to prefix followed by `:index:hash`. So, for a prefix of `Foo`, it would
* use `Foo:index:hash`.
*/
indexHashName?: string;
/** The data structure used to store the {@link Entity} in Redis. Can be set
* to either `JSON` or `HASH`. Defaults to JSON.
*/
dataStructure?: DataStructure;
/**
* A function that generates a random entityId. Defaults to a function that generates
* [ULIDs](https://github.com/ulid/spec). Combined with prefix to generate a Redis key.
* If prefix is `Foo` and idStratgey returns `12345` then the generated key would be
* `Foo:12345`.
*/
idStrategy?: IdStrategy;
/**
* Configures the usage of stop words. Valid values are `OFF`, `DEFAULT`, and `CUSTOM`.
* Setting this to `OFF` disables all stop words. Setting this to `DEFAULT` uses the
* stop words intrinsic to RediSearch. Setting this to `CUSTOM` tells RediSearch to
* use the stop words in `stopWords`.
*/
useStopWords?: StopWordOptions;
/**
* Stop words to be used by this schema. If `useStopWords` is
* anything other than `CUSTOM`, this option is ignored.
*/
stopWords?: Array<string>;
};
/**
* Defines a schema that determines how an {@link Entity} is mapped
* to Redis data structures. Construct by passing in a schema name,
* a {@link SchemaDefinition}, and optionally {@link SchemaOptions}:
*
* ```typescript
* const schema = new Schema('foo', {
* aString: { type: 'string' },
* aNumber: { type: 'number' },
* aBoolean: { type: 'boolean' },
* someText: { type: 'text' },
* aPoint: { type: 'point' },
* aDate: { type: 'date' },
* someStrings: { type: 'string[]' }
* }, {
* dataStructure: 'HASH'
* })
* ```
*
* A Schema is primarily used by a {@link Repository} which requires a Schema in
* its constructor.
*/
declare class Schema {
#private;
/**
* Constructs a Schema.
*
* @param schemaName The name of the schema. Prefixes the ID when creating Redis keys.
* @param schemaDef Defines all of the fields for the Schema and how they are mapped to Redis.
* @param options Additional options for this Schema.
*/
constructor(schemaName: string, schemaDef: SchemaDefinition, options?: SchemaOptions);
/**
* The name of the schema. Prefixes the ID when creating Redis keys. Combined
* with the results of idStrategy to generate a key. If name is `foo` and
* idStrategy returns `12345` then the generated key would be `foo:12345`.
*/
get schemaName(): string;
/** The {@link Field | Fields} defined by this Schema. */
get fields(): Field[];
/**
* Gets a single {@link Field} defined by this Schema.
*
* @param name The name of the {@link Field} in this Schema.
* @returns The {@link Field}, or null of not found.
*/
fieldByName(name: string): Field | null;
/** The configured name for the RediSearch index for this Schema. */
get indexName(): string;
/** The configured name for the RediSearch index hash for this Schema. */
get indexHashName(): string;
/**
* The configured data structure, a string with the value of either `HASH` or `JSON`,
* that this Schema uses to store {@link Entity | Entities} in Redis.
*/
get dataStructure(): DataStructure;
/**
* The configured usage of stop words, a string with the value of either `OFF`, `DEFAULT`,
* or `CUSTOM`. See {@link SchemaOptions} for more details.
*/
get useStopWords(): StopWordOptions;
/**
* The configured stop words. Ignored if {@link Schema.useStopWords} is anything other
* than `CUSTOM`.
*/
get stopWords(): Array<string>;
/**
* Generates a unique string using the configured {@link IdStrategy}.
*
* @returns The generated id.
*/
generateId(): Promise<string>;
/**
* A hash for this Schema that is used to determine if the Schema has been
* changed when calling {@link Repository#createIndex}.
*/
get indexHash(): string;
}
/**
* Abstract base class used extensively with {@link Search}.
*/
declare abstract class Where {
/**
* Converts this {@link Where} into a portion of a RediSearch query.
*/
abstract toString(): string;
}
type Units = 'm' | 'km' | 'ft' | 'mi';
/** A function that defines a circle for `.inCircle` searches. */
type CircleFunction = (circle: Circle) => Circle;
/** A builder that defines a circle. */
declare class Circle {
/** @internal */
longitudeOfOrigin: number;
/** @internal */
latitudeOfOrigin: number;
/** @internal */
size: number;
/** @internal */
units: Units;
/**
* Sets the longitude. If not set, defaults to 0.0.
*
* @param value The longitude.
* @returns This instance.
*/
longitude(value: number): this;
/**
* Sets the latitude. If not set, defaults to 0.0.
*
* @param value The latitude.
* @returns This instance.
*/
latitude(value: number): this;
/**
* Sets the origin of the circle using a {@link Point}. If not
* set, defaults to [Null Island](https://en.wikipedia.org/wiki/Null_Island).
*
* @param point A {@link Point} containing the longitude and latitude of the origin.
* @returns This instance.
*/
origin(point: Point): Circle;
/**
* Sets the origin of the circle. If not set, defaults to
* [Null Island](https://en.wikipedia.org/wiki/Null_Island).
*
* @param longitude The longitude.
* @param latitude The latitude.
* @returns This instance.
*/
origin(longitude: number, latitude: number): Circle;
/**
* Sets the radius of the {@link Circle}. Defaults to 1. If units are
* not specified, defaults to meters.
*
* @param size The radius of the circle.
* @returns This instance.
*/
radius(size: number): this;
/**
* Sets the units to meters.
* @returns This instance.
*/
get m(): this;
/**
* Sets the units to meters.
* @returns This instance.
*/
get meter(): this;
/**
* Sets the units to meters.
* @returns This instance.
*/
get meters(): this;
/**
* Sets the units to kilometers.
* @returns This instance.
*/
get km(): this;
/**
* Sets the units to kilometers.
* @returns This instance.
*/
get kilometer(): this;
/**
* Sets the units to kilometers.
* @returns This instance.
*/
get kilometers(): this;
/**
* Sets the units to feet.
* @returns This instance.
*/
get ft(): this;
/**
* Sets the units to feet.
* @returns This instance.
*/
get foot(): this;
/**
* Sets the units to feet.
* @returns This instance.
*/
get feet(): this;
/**
* Sets the units to miles.
* @returns This instance.
*/
get mi(): this;
/**
* Sets the units to miles.
* @returns This instance.
*/
get mile(): this;
/**
* Sets the units to miles.
* @returns This instance.
*/
get miles(): this;
}
/**
* Interface with all the methods from all the concrete
* classes under {@link WhereField}.
*/
interface WhereField extends Where {
/**
* Adds an equals comparison to the query.
*
* NOTE: this function is not available for strings where full-text
* search is enabled. In that scenario, use `.match`.
* @param value The value to be compared
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
eq(value: string | number | boolean | Date): Search;
/**
* Adds an equals comparison to the query.
*
* NOTE: this function is not available for strings where full-text
* search is enabled. In that scenario, use `.match`.
* @param value The value to be compared
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
equal(value: string | number | boolean | Date): Search;
/**
* Adds an equals comparison to the query.
*
* NOTE: this function is not available for strings where full-text
* search is enabled. In that scenario, use `.match`.
* @param value The value to be compared
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
equals(value: string | number | boolean | Date): Search;
/**
* Adds an equals comparison to the query.
*
* NOTE: this function is not available for strings where full-text
* search is enabled. In that scenario, use `.match`.
* @param value The value to be compared
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
equalTo(value: string | number | boolean | Date): Search;
/**
* Adds a full-text search comparison to the query.
* @param value The word or phrase sought.
* @param options.fuzzyMatching Whether to use fuzzy matching to find the sought word or phrase. Defaults to `false`.
* @param options.levenshteinDistance The levenshtein distance to use for fuzzy matching. Supported values are `1`, `2`, and `3`. Defaults to `1`.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
match(value: string | number | boolean, options?: {
fuzzyMatching?: boolean;
levenshteinDistance?: 1 | 2 | 3;
}): Search;
/**
* Adds a full-text search comparison to the query.
* @param value The word or phrase sought.
* @param options.fuzzyMatching Whether to use fuzzy matching to find the sought word or phrase. Defaults to `false`.
* @param options.levenshteinDistance The levenshtein distance to use for fuzzy matching. Supported values are `1`, `2`, and `3`. Defaults to `1`.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
matches(value: string | number | boolean, options?: {
fuzzyMatching?: boolean;
levenshteinDistance?: 1 | 2 | 3;
}): Search;
/**
* Adds a full-text search comparison to the query that matches an exact word or phrase.
* @param value The word or phrase sought.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
matchExact(value: string | number | boolean): Search;
/**
* Adds a full-text search comparison to the query that matches an exact word or phrase.
* @param value The word or phrase sought.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
matchExactly(value: string | number | boolean): Search;
/**
* Adds a full-text search comparison to the query that matches an exact word or phrase.
* @param value The word or phrase sought.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
matchesExactly(value: string | number | boolean): Search;
/**
* Makes a call to {@link WhereField.match} a {@link WhereField.matchExact} call. Calling
* this multiple times will have no effect.
* @returns this.
*/
readonly exact: WhereField;
/**
* Makes a call to {@link WhereField.match} a {@link WhereField.matchExact} call. Calling
* this multiple times will have no effect.
* @returns this.
*/
readonly exactly: WhereField;
/**
* Adds a boolean match with a value of `true` to the query.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
true(): Search;
/**
* Adds a boolean match with a value of `false` to the query.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
false(): Search;
/**
* Adds a greater than comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
gt(value: string | number | Date): Search;
/**
* Adds a greater than comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
greaterThan(value: string | number | Date): Search;
/**
* Adds a greater than or equal to comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
gte(value: string | number | Date): Search;
/**
* Adds a greater than or equal to comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
greaterThanOrEqualTo(value: string | number | Date): Search;
/**
* Adds a less than comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
lt(value: string | number | Date): Search;
/**
* Adds a less than comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
lessThan(value: string | number | Date): Search;
/**
* Adds a less than or equal to comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
lte(value: string | number | Date): Search;
/**
* Adds a less than or equal to comparison against a field to the search query.
* @param value The value to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
lessThanOrEqualTo(value: string | number | Date): Search;
/**
* Adds an inclusive range comparison against a field to the search query.
* @param lower The lower bound of the range.
* @param upper The upper bound of the range.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
between(lower: string | number | Date, upper: string | number | Date): Search;
/**
* Adds a whole-string match for a value within a string array to the search query.
* @param value The string to be matched.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
contain(value: string): Search;
/**
* Adds a whole-string match for a value within a string array to the search query.
* @param value The string to be matched.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
contains(value: string): Search;
/**
* Adds a whole-string match against a string array to the query. If any of the provided
* strings in `value` is matched in the array, this matched.
* @param value An array of strings that you want to match one of.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
containOneOf(...value: Array<string>): Search;
/**
* Adds a whole-string match against a string array to the query. If any of the provided
* strings in `value` is matched in the array, this matched.
* @param value An array of strings that you want to match one of.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
containsOneOf(...value: Array<string>): Search;
/**
* Adds a search for points that fall within a defined circle.
* @param circleFn A function that returns a {@link Circle} instance defining the search area.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
inCircle(circleFn: CircleFunction): Search;
/**
* Adds a search for points that fall within a defined radius.
* @param circleFn A function that returns a {@link Circle} instance defining the search area.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
inRadius(circleFn: CircleFunction): Search;
/**
* Add a search for an exact UTC datetime to the query.
* @param value The datetime to match.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
on(value: string | number | Date): Search;
/**
* Add a search that matches all datetimes *before* the provided UTC datetime to the query.
* @param value The datetime to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
before(value: string | number | Date): Search;
/**
* Add a search that matches all datetimes *after* the provided UTC datetime to the query.
* @param value The datetime to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
after(value: string | number | Date): Search;
/**
* Add a search that matches all datetimes *on or before* the provided UTC datetime to the query.
* @param value The datetime to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
onOrBefore(value: string | number | Date): Search;
/**
* Add a search that matches all datetimes *on or after* the provided UTC datetime to the query.
* @param value The datetime to compare against.
* @returns The {@link Search} that was called to create this {@link WhereField}.
*/
onOrAfter(value: string | number | Date): Search;
}
/**
* Abstract base class that all fields you want to filter
* with extend. When you call {@link Search.where}, a
* subclass of this is returned.
*/
declare abstract class WhereField {
private negated;
/** @internal */
protected search: Search;
/** @internal */
protected field: Field;
/** @internal */
constructor(search: Search, field: Field);
/**
* Returns the current instance. Syntactic sugar to make your code more fluent.
* @returns this
*/
get is(): this;
/**
* Returns the current instance. Syntactic sugar to make your code more fluent.
* @returns this
*/
get does(): this;
/**
* Negates the query on the field, cause it to match when the condition is
* *not* met. Calling this multiple times will negate the negation.
* @returns this
*/
get not(): this;
abstract toString(): string;
/** @internal */
protected negate(): void;
/** @internal */
protected buildQuery(valuePortion: string): string;
/** @internal */
protected escapePunctuation(value: string): string;
/** @internal */
protected escapePunctuationAndSpaces(value: string): string;
}
/**
* A function that takes a {@link Search} and returns a {@link Search}. Used in nested queries.
* @template TEntity The type of {@link Entity} being sought.
*/
type SubSearchFunction = (search: Search) => Search;
type SortOptions = {
BY: string;
DIRECTION: 'ASC' | 'DESC';
};
/**
* Abstract base class for {@link Search} and {@link RawSearch} that
* contains methods to return search results.
* @template TEntity The type of {@link Entity} being sought.
*/
declare abstract class AbstractSearch {
/** @internal */
protected schema: Schema;
/** @internal */
protected client: Client;
/** @internal */
protected sortOptions?: SortOptions;
/** @internal */
constructor(schema: Schema, client: Client);
/** @internal */
abstract get query(): string;
/**
* Applies an ascending sort to the query.
* @param field The field to sort by.
* @returns this
*/
sortAscending(field: string): AbstractSearch;
/**
* Alias for {@link Search.sortDescending}.
*/
sortDesc(field: string): AbstractSearch;
/**
* Applies a descending sort to the query.
* @param field The field to sort by.
* @returns this
*/
sortDescending(field: string): AbstractSearch;
/**
* Alias for {@link Search.sortAscending}.
*/
sortAsc(field: string): AbstractSearch;
/**
* Applies sorting for the query.
* @param field The field to sort by.
* @param order The order of returned {@link Entity | Entities} Defaults to `ASC` (ascending) if not specified
* @returns this
*/
sortBy(fieldName: string, order?: 'ASC' | 'DESC'): AbstractSearch;
/**
* Finds the {@link Entity} with the minimal value for a field.
* @param field The field with the minimal value.
* @returns The {@link Entity} with the minimal value
*/
min(field: string): Promise<Entity | null>;
/**
* Finds the entity ID with the minimal value for a field.
* @param field The field with the minimal value.
* @returns The entity ID with the minimal value
*/
minId(field: string): Promise<string | null>;
/**
* Finds the key name in Redis with the minimal value for a field.
* @param field The field with the minimal value.
* @returns The key name with the minimal value
*/
minKey(field: string): Promise<string | null>;
/**
* Finds the {@link Entity} with the maximal value for a field.
* @param field The field with the maximal value.
* @returns The entity ID {@link Entity} with the maximal value
*/
max(field: string): Promise<Entity | null>;
/**
* Finds the entity ID with the maximal value for a field.
* @param field The field with the maximal value.
* @returns The entity ID with the maximal value
*/
maxId(field: string): Promise<string | null>;
/**
* Finds the key name in Redis with the maximal value for a field.
* @param field The field with the maximal value.
* @returns The key name with the maximal value
*/
maxKey(field: string): Promise<string | null>;
/**
* Returns the number of {@link Entity | Entities} that match this query.
* @returns
*/
count(): Promise<number>;
/**
* Returns a page of {@link Entity | Entities} that match this query.
* @param offset The offset for where to start returning {@link Entity | Entities}.
* @param count The number of {@link Entity | Entities} to return.
* @returns An array of {@link Entity | Entities} matching the query.
*/
page(offset: number, count: number): Promise<Entity[]>;
/**
* Returns a page of entity IDs that match this query.
* @param offset The offset for where to start returning entity IDs.
* @param count The number of entity IDs to return.
* @returns An array of strings matching the query.
*/
pageOfIds(offset: number, count: number): Promise<string[]>;
/**
* Returns a page of key names in Redis that match this query.
* @param offset The offset for where to start returning key names.
* @param count The number of key names to return.
* @returns An array of strings matching the query.
*/
pageOfKeys(offset: number, count: number): Promise<string[]>;
/**
* Returns the first {@link Entity} that matches this query.
*/
first(): Promise<Entity | null>;
/**
* Returns the first entity ID that matches this query.
*/
firstId(): Promise<string | null>;
/**
* Returns the first key name that matches this query.
*/
firstKey(): Promise<string | null>;
/**
* Returns all the {@link Entity | Entities} that match this query. This method
* makes multiple calls to Redis until all the {@link Entity | Entities} are returned.
* You can specify the batch size by setting the `pageSize` property on the
* options:
*
* ```typescript
* const entities = await repository.search().returnAll({ pageSize: 100 })
* ```
*
* @param options Options for the call.
* @param options.pageSize Number of {@link Entity | Entities} returned per batch.
* @returns An array of {@link Entity | Entities} matching the query.
*/
all(options?: {
pageSize: number;
}): Promise<Entity[]>;
/**
* Returns all the entity IDs that match this query. This method
* makes multiple calls to Redis until all the entity IDs are returned.
* You can specify the batch size by setting the `pageSize` property on the
* options:
*
* ```typescript
* const keys = await repository.search().returnAllIds({ pageSize: 100 })
* ```
*
* @param options Options for the call.
* @param options.pageSize Number of entity IDs returned per batch.
* @returns An array of entity IDs matching the query.
*/
allIds(options?: {
pageSize: number;
}): Promise<string[]>;
/**
* Returns all the key names in Redis that match this query. This method
* makes multiple calls to Redis until all the key names are returned.
* You can specify the batch size by setting the `pageSize` property on the
* options:
*
* ```typescript
* const keys = await repository.search().returnAllKeys({ pageSize: 100 })
* ```
*
* @param options Options for the call.
* @param options.pageSize Number of key names returned per batch.
* @returns An array of key names matching the query.
*/
allKeys(options?: {
pageSize: number;
}): Promise<string[]>;
/**
* Returns the current instance. Syntactic sugar to make your code more fluent.
* @returns this
*/
get return(): AbstractSearch;
/**
* Alias for {@link Search.min}.
*/
returnMin(field: string): Promise<Entity | null>;
/**
* Alias for {@link Search.minId}.
*/
returnMinId(field: string): Promise<string | null>;
/**
* Alias for {@link Search.minKey}.
*/
returnMinKey(field: string): Promise<string | null>;
/**
* Alias for {@link Search.max}.
*/
returnMax(field: string): Promise<Entity | null>;
/**
* Alias for {@link Search.maxId}.
*/
returnMaxId(field: string): Promise<string | null>;
/**
* Alias for {@link Search.maxKey}.
*/
returnMaxKey(field: string): Promise<string | null>;
/**
* Alias for {@link Search.count}.
*/
returnCount(): Promise<number>;
/**
* Alias for {@link Search.page}.
*/
returnPage(offset: number, count: number): Promise<Entity[]>;
/**
* Alias for {@link Search.pageOfIds}.
*/
returnPageOfIds(offset: number, count: number): Promise<string[]>;
/**
* Alias for {@link Search.pageOfKeys}.
*/
returnPageOfKeys(offset: number, count: number): Promise<string[]>;
/**
* Alias for {@link Search.first}.
*/
returnFirst(): Promise<Entity | null>;
/**
* Alias for {@link Search.firstId}.
*/
returnFirstId(): Promise<string | null>;
/**
* Alias for {@link Search.firstKey}.
*/
returnFirstKey(): Promise<string | null>;
/**
* Alias for {@link Search.all}.
*/
returnAll(options?: {
pageSize: number;
}): Promise<Entity[]>;
/**
* Alias for {@link Search.allIds}.
*/
returnAllIds(options?: {
pageSize: number;
}): Promise<string[]>;
/**
* Alias for {@link Search.allKeys}.
*/
returnAllKeys(options?: {
pageSize: number;
}): Promise<string[]>;
private allThings;
private callSearch;
}
/**
* Entry point to raw search which allows using raw RediSearch queries
* against Redis OM. Requires that RediSearch (and optionally RedisJSON) be
* installed.
* @template TEntity The type of {@link Entity} being sought.
*/
declare class RawSearch extends AbstractSearch {
private rawQuery;
/** @internal */
constructor(schema: Schema, client: Client, query?: string);
/** @internal */
get query(): string;
}
/**
* Entry point to fluent search. This is the default Redis OM experience.
* Requires that RediSearch (and optionally RedisJSON) be installed.
* @template TEntity The type of {@link Entity} being sought.
*/
declare class Search extends AbstractSearch {
private rootWhere?;
/** @internal */
get query(): string;
/**
* Sets up a query matching a particular field. If there are multiple calls
* to {@link Search.where}, they are treated logically as AND.
* @param field The field to filter on.
* @returns A subclass of {@link WhereField} matching the type of the field.
*/
where(field: string): WhereField;
/**
* Sets up a nested search. If there are multiple calls to {@link Search.where},
* they are treated logically as AND.
* @param subSearchFn A function that takes a {@link Search} and returns another {@link Search}.
* @returns `this`.
*/
where(subSearchFn: SubSearchFunction): Search;
/**
* Sets up a query matching a particular field as a logical AND.
* @param field The field to filter on.
* @returns A subclass of {@link WhereField} matching the type of the field.
*/
and(field: string): WhereField;
/**
* Sets up a nested search as a logical AND.
* @param subSearchFn A function that takes a {@link Search} and returns another {@link Search}.
* @returns `this`.
*/
and(subSearchFn: SubSearchFunction): Search;
/**
* Sets up a query matching a particular field as a logical OR.
* @param field The field to filter on.
* @returns A subclass of {@link WhereField} matching the type of the field.
*/
or(field: string): WhereField;
/**
* Sets up a nested search as a logical OR.
* @param subSearchFn A function that takes a {@link Search} and returns another {@link Search}.
* @returns `this`.
*/
or(subSearchFn: SubSearchFunction): Search;
private anyWhere;
private anyWhereForField;
private anyWhereForFunction;
private createWhere;
}
/**
* A repository is the main interaction point for reading, writing, and
* removing {@link Entity | Entities} from Redis. Create one by calling
* {@link Client.fetchRepository} and passing in a {@link Schema}. Then
* use the {@link Repository#fetch}, {@link Repository#save}, and
* {@link Repository#remove} methods to manage your data:
*
* ```typescript
* const repository = client.fetchRepository(schema)
*
* const foo = await repository.fetch('01FK6TCJBDK41RJ766A4SBWDJ9')
* foo.aString = 'bar'
* foo.aBoolean = false
* await repository.save(foo)
* ```
*
* Use the repository to create a new instance of an {@link Entity}
* before you save it:
*
* ```typescript
* const foo = await repository.createEntity()
* foo.aString = 'bar'
* foo.aBoolean = false
* await repository.save(foo)
* ```
*
* If you want to use the {@link Repository#search} method, you need to create an index
* first, and you need RediSearch or RedisJSON installed on your instance of Redis:
*
* ```typescript
* await repository.createIndex()
* const entities = await repository.search()
* .where('aString').eq('bar')
* .and('aBoolean').is.false().returnAll()
* ```
*/
declare class Repository {
#private;
private client;
/**
* Creates a new {@link Repository}.
*
* @param schema The schema defining that data in the repository.
* @param client A client to talk to Redis.
*/
constructor(schema: Schema, clientOrConnection: Client | RedisConnection);
/**
* Creates an index in Redis for use by the {@link Repository#search} method.
* Does not create a new index if the index hasn't changed. Requires that
* RediSearch and RedisJSON are installed on your instance of Redis.
*/
createIndex(): Promise<void>;
/**
* Removes an existing index from Redis. Use this method if you want to swap out your index
* because your {@link Entity} has changed. Requires that RediSearch and RedisJSON are installed
* on your instance of Redis.
*/
dropIndex(): Promise<void>;
/**
* Insert or update an {@link Entity} to Redis using its entityId property
* if present. If it's not, one is generated.
*
* @param entity The Entity to save.
* @returns A copy of the provided Entity with EntityId and EntityKeyName properties added.
*/
save(entity: Entity): Promise<Entity>;
/**
* Insert or update the {@link Entity} to Redis using the provided entityId.
*
* @param id The id to save the Entity under.
* @param entity The Entity to save.
* @returns A copy of the provided Entity with EntityId and EntityKeyName properties added.
*/
save(id: string, entity: Entity): Promise<Entity>;
/**
* Read and return an {@link Entity} from Redis for the given id. If
* the {@link Entity} is not found, returns an empty {@link Entity}.
*
* @param id The ID of the {@link Entity} you seek.
* @returns The matching Entity.
*/
fetch(id: string): Promise<Entity>;
/**
* Read and return the {@link Entity | Entities} from Redis with the given IDs. If
* a particular {@link Entity} is not found, returns that {@link Entity} as empty.
*
* @param ids The IDs of the {@link Entity | Entities} you seek.
* @returns The matching Entities.
*/
fetch(...ids: string[]): Promise<Entity[]>;
/**
* Read and return the {@link Entity | Entities} from Redis with the given IDs. If
* a particular {@link Entity} is not found, returns that {@link Entity} as empty.
*
* @param ids The IDs of the {@link Entity | Entities} you seek.
* @returns The matching Entities.
*/
fetch(ids: string[]): Promise<Entity[]>;
/**
* Remove an {@link Entity} from Redis for the given id. If the {@link Entity} is
* not found, does nothing.
*
* @param id The ID of the {@link Entity} you wish to delete.
*/
remove(id: string): Promise<void>;
/**
* Remove the {@link Entity | Entities} from Redis for the given ids. If a
* particular {@link Entity} is not found, does nothing.
*
* @param ids The IDs of the {@link Entity | Entities} you wish to delete.
*/
remove(...ids: string[]): Promise<void>;
/**
* Remove the {@link Entity | Entities} from Redis for the given ids. If a
* particular {@link Entity} is not found, does nothing.
*
* @param ids The IDs of the {@link Entity | Entities} you wish to delete.
*/
remove(ids: string[]): Promise<void>;
/**
* Set the time to live of the {@link Entity}. If the {@link Entity} is not
* found, does nothing.
*
* @param id The ID of the {@link Entity} to set and expiration for.
* @param ttlInSeconds The time to live in seconds.
*/
expire(id: string, ttlInSeconds: number): Promise<void>;
/**
* Set the time to live of the {@link Entity | Entities} in Redis with the given
* ids. If a particular {@link Entity} is not found, does nothing.
*
* @param ids The IDs of the {@link Entity | Entities} you wish to delete.
*/
expire(ids: string[], ttlInSeconds: number): Promise<void>;
/**
* Use Date object to set the {@link Entity}'s time to live. If the {@link Entity}
* is not found, does nothing.
*
* @param id The ID of the {@link Entity} to set an expiration date for.
* @param expirationDate The time the data should expire.
*/
expireAt(id: string, expirationDate: Date): Promise<void>;
/**
* Use Date object to set the {@link Entity | Entities} in Redis with the given
* ids. If a particular {@link Entity} is not found, does nothing.
*
* @param ids The IDs of the {@link Entity | Entities} to set an expiration date for.
* @param expirationDate The time the data should expire.
*/
expireAt(ids: string[], expirationDate: Date): Promise<void>;
/**
* Kicks off the process of building a query. Requires that RediSearch (and optionally
* RedisJSON) be installed on your instance of Redis.
*
* @returns A {@link Search} object.
*/
search(): Search;
/**
* Creates a search that bypasses Redis OM and instead allows you to execute a raw
* RediSearch query. Requires that RediSearch (and optionally RedisJSON) be installed
* on your instance of Redis.
*
* Refer to https://redis.io/docs/stack/search/reference/query_syntax/ for details on
* RediSearch query syntax.
*
* @query The raw RediSearch query you want to rune.
* @returns A {@link RawSearch} object.
*/
searchRaw(query: string): RawSearch;
private writeEntity;
private readEntities;
private writeEntityToHash;
private readEntitiesFromHash;
private writeEntityToJson;
private readEntitiesFromJson;
private makeKeys;
private makeKey;
}
/** A conventional Redis connection. */
type RedisClientConnection = ReturnType<typeof createClient>;
/** A clustered Redis connection. */
type RedisClusterConnection = ReturnType<typeof createCluster>;
/** A Redis connection, clustered or conventional. */
type RedisConnection = RedisClientConnection | RedisClusterConnection;
/** @internal This is a defintion for the type that calls to ft.search in Node Redis return. */
type SearchResults = {
total: number;
documents: SearchDocument[];
};
/** @internal This is a defintion for the return type of calls to ft.search in Node Redis. */
type SearchDocument = {
id: string;
value: {
[key: string]: any;
};
};
/** @internal */
type RedisHashData = {
[key: string]: string;
};
/** @internal */
type RedisJsonData = {
[key: string]: any;
};
/** @internal */
type SearchDataStructure = 'HASH' | 'JSON';
/**
* @internal This is a simplified redefintion of the CreateOptions type that is not exported by Node Redis.
* TODO: Remove this type once CreateOptions is exported by Node Redis.
* https://github.com/redis/node-redis/blob/master/packages/search/lib/commands/CREATE.ts#L4
*/
type CreateOptions = {
ON: SearchDataStructure;
PREFIX: string;
STOPWORDS?: string[];
};
/**
* A Client is the starting point for working with Redis OM. Clients manage the
* connection to Redis and provide limited functionality for executing Redis commands.
* Create a client and open it before you use it:
*
* ```typescript
* const client = new Client()
* await client.open()
* ```
*
* A Client is primarily used by a {@link Repository} which requires a client in
* its constructor.
*
* @deprecated Just used Node Redis client directly and pass it to the Repository.
*/
declare class Client {
#private;
/** Returns the underlying Node Redis connection being used. */
get redis(): RedisConnection | undefined;
/**
* Attaches an existing Node Redis connection to this Redis OM client. Closes
* any existing connection.
*
* @param connection An existing Node Redis client.
* @returns This {@link Client} instance.
*/
use(connection: RedisConnection): Promise<Client>;
/**
* Attaches an existing Node Redis connection to this Redis OM client. Does
* not close any existing connection.
*
* @param connection An existing Node Redis client.
* @returns This {@link Client} instance.
*/
useNoClose(connection: RedisConnection): Client;
/**
* Open a connection to Redis at the provided URL.
*
* @param url A URL to Redis as defined with the [IANA](https://www.iana.org/assignments/uri-schemes/prov/redis).
* @returns This {@link Client} instance.
*/
open(url?: string): Promise<Client>;
/**
* Creates a repository for the given schema.
*
* @param schema The schema.
* @returns A repository for the provided schema.
*/
fetchRepository(schema: Schema): Repository;
/**
* Close the connection to Redis.
*/
close(): Promise<void>;
/** @internal */
createIndex(indexName: string, schema: RediSearchSchema, options: CreateOptions): Promise<void>;
/** @internal */
dropIndex(indexName: string): Promise<void>;
/** @internal */
search(indexName: string, query: string, options?: SearchOptions): Promise<SearchResults>;
/** @internal */
unlink(...keys: string[]): Promise<void>;
/** @internal */
expire(key: string, ttl: number): Promise<void>;
/** @internal */
expireAt(key: string, timestamp: Date): Promise<void>;
/** @internal */
get(key: string): Promise<string | null>;
/** @internal */
set(key: string, value: string): Promise<void>;
/** @internal */
hgetall(key: string): Promise<RedisHashData>;
/** @internal */
hsetall(key: string, data: RedisHashData): Promise<void>;
/** @internal */
jsonget(key: string): Promise<RedisJsonData | null>;
/** @internal */
jsonset(key: string, data: RedisJsonData): Promise<void>;
/**
* @returns Whether a connection is already open.
*/
isOpen(): boolean;
}
declare class RedisOmError extends Error {
}
declare class InvalidInput extends RedisOmError {
}
declare class NullJsonInput extends InvalidInput {
#private;
constructor(field: Field);
get fieldName(): string;
get fieldType(): FieldType;
get jsonPath(): string;
}
declare class InvalidJsonInput extends InvalidInput {
#private;
constructor(field: Field);
get fieldName(): string;
get fieldType(): FieldType;
get jsonPath(): string;
}
declare class InvalidHashInput extends InvalidInput {
#private;
constructor(field: Field);
get fieldName(): string;
get fieldType(): FieldType;
}
declare class NestedHashInput extends InvalidInpu