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

[Do not merge] : [@azure/cosmos] Add Full text search support for cosmos-explorer #31710

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
360d332
Feature/full text functionality (#31582)
topshot99 Oct 30, 2024
8dc5356
Feature/full text functionality (#31618)
topshot99 Nov 3, 2024
46bd786
Feature/fts (#31619)
topshot99 Nov 3, 2024
3e36c96
Feature/full text functionality (#31638)
topshot99 Nov 5, 2024
e799caf
Feature/full text functionality (#31640)
topshot99 Nov 5, 2024
1c4870c
Feature/full text functionality (#31652)
topshot99 Nov 6, 2024
f7d80ca
Feature/full text functionality (#31659)
topshot99 Nov 6, 2024
2a7f44d
Feature/full text functionality (#31682)
topshot99 Nov 8, 2024
dcbd5a4
Feature/full text functionality (#31687)
topshot99 Nov 8, 2024
6332df2
Feature/full text functionality (#31688)
topshot99 Nov 8, 2024
2d64ca9
Feature/full text functionality (#31689)
topshot99 Nov 8, 2024
aaf45f4
Feature/full text functionality (#31691)
topshot99 Nov 8, 2024
636e745
Feature/full text functionality (#31692)
topshot99 Nov 8, 2024
96647b5
Add RU cap
amanrao23 Nov 9, 2024
b859b13
fix fts+ruCap
amanrao23 Nov 9, 2024
d4799a6
Remove disableMakeSetMakeList option
amanrao23 Nov 11, 2024
16c4ca4
Update executionContexts options
amanrao23 Nov 11, 2024
26d0929
Enable tests
amanrao23 Nov 11, 2024
9c8cd6d
Update changelog
amanrao23 Nov 11, 2024
6a00339
Update formatting
amanrao23 Nov 11, 2024
3349ef2
fix lint
amanrao23 Nov 11, 2024
82b2974
fix lint
amanrao23 Nov 11, 2024
f348d4d
skip tests for pipeline
amanrao23 Nov 11, 2024
00f5aef
fix ru cap check
amanrao23 Nov 11, 2024
7ae8287
fix format
amanrao23 Nov 11, 2024
fa097e0
fix package name
amanrao23 Nov 11, 2024
af72225
Update ChangeLog
amanrao23 Nov 11, 2024
e46c167
update executionContext options interface
amanrao23 Nov 11, 2024
28901d1
Fix formatting
amanrao23 Nov 11, 2024
6457b0e
Fix FetchAll returning empty result
amanrao23 Nov 13, 2024
bd40fe2
Cherry-pick from fts
amanrao23 Nov 13, 2024
c38f6d6
skip fts emulator tests
amanrao23 Nov 13, 2024
a9fc970
fix fetchAll
amanrao23 Nov 13, 2024
02f24b8
fix for gw placeholder issue
amanrao23 Nov 14, 2024
fa230a2
Update Changelog
amanrao23 Nov 15, 2024
4bb6efa
Update Changelog
amanrao23 Nov 15, 2024
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
4 changes: 4 additions & 0 deletions sdk/cosmosdb/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ extends:
Artifacts:
- name: azure-cosmos
safeName: azurecosmos
skipPublishDocMs: true
skipPublishDocGithubIo: true
skipPublishDevFeed: true
skipUpdatePackageVersion: true
9 changes: 4 additions & 5 deletions sdk/cosmosdb/cosmos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# Release History

## 4.1.2 (Unreleased)
## 4.2.0-beta.1 (2024-11-15)

### Features Added
- Add support for Full text search and Hybrid Ranking.

### Breaking Changes

### Bugs Fixed
- Addition of full text policy.

### Other Changes
- We have implemented support for Request Unit (RU) caps in Query operations. Clients can now seamlessly integrate RU caps into their fetch functions by specifying the desired cap within the operation options. If the specified RU cap is surpassed during the operation, clients will promptly receive an error notification, providing enhanced control and transparency over resource consumption.

## 4.1.1 (2024-08-30)

Expand Down
2 changes: 1 addition & 1 deletion sdk/cosmosdb/cosmos/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure/cosmos",
"version": "4.1.2",
"version": "4.2.0-beta.1",
"description": "Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API",
"sdk-type": "client",
"keywords": [
Expand Down
54 changes: 49 additions & 5 deletions sdk/cosmosdb/cosmos/review/cosmos.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ export const Constants: {
MinimumInclusiveEffectivePartitionKey: string;
MaximumExclusiveEffectivePartitionKey: string;
};
NonStreamingQueryDefaultRUThreshold: number;
AllVersionsAndDeletesChangeFeedWireFormatVersion: string;
ChangeFeedIfNoneMatchStartFromNowHeader: string;
};
Expand Down Expand Up @@ -634,6 +635,7 @@ export interface ContainerDefinition {
computedProperties?: ComputedProperty[];
conflictResolutionPolicy?: ConflictResolutionPolicy;
defaultTtl?: number;
fullTextPolicy?: FullTextPolicy;
geospatialConfig?: {
type: GeospatialType;
};
Expand Down Expand Up @@ -1095,6 +1097,23 @@ export class FeedResponse<TResource> {
readonly resources: TResource[];
}

// @public
export interface FullTextIndex {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullTextSearchIndex, FullTextSearchPath, FullTextSearchPolicy might be clearer, just fullText doesn't tell me much

path: string;
}

// @public
export interface FullTextPath {
language: string;
path: string;
}

// @public
export interface FullTextPolicy {
defaultLanguage: string;
fullTextPaths: FullTextPath[];
}

// @public (undocumented)
export type GatewayStatistics = {
activityId?: string;
Expand Down Expand Up @@ -1161,6 +1180,15 @@ export enum HTTPMethod {
put = "PUT"
}

// @public
export interface HybridSearchQueryInfo {
componentQueryInfos: QueryInfo[];
globalStatisticsQuery: string;
requiresGlobalStatistics: boolean;
skip: number;
take: number;
}

// @public (undocumented)
export interface Index {
// (undocumented)
Expand Down Expand Up @@ -1192,6 +1220,7 @@ export interface IndexingPolicy {
automatic?: boolean;
compositeIndexes?: CompositePath[][];
excludedPaths?: IndexedPath[];
fullTextIndexes?: FullTextIndex[];
includedPaths?: IndexedPath[];
indexingMode?: keyof typeof IndexingMode;
// (undocumented)
Expand Down Expand Up @@ -1452,10 +1481,11 @@ export type OperationWithItem = OperationBase & {

// @public (undocumented)
export interface PartitionedQueryExecutionInfo {
hybridSearchQueryInfo?: HybridSearchQueryInfo;
// (undocumented)
partitionedQueryExecutionInfoVersion: number;
// (undocumented)
queryInfo: QueryInfo;
queryInfo?: QueryInfo;
// (undocumented)
queryRanges: QueryRange[];
}
Expand Down Expand Up @@ -1671,11 +1701,11 @@ export interface QueryInfo {
export class QueryIterator<T> {
// Warning: (ae-forgotten-export) The symbol "FetchFunctionCallback" needs to be exported by the entry point index.d.ts
constructor(clientContext: ClientContext, query: SqlQuerySpec | string, options: FeedOptions, fetchFunctions: FetchFunctionCallback | FetchFunctionCallback[], resourceLink?: string, resourceType?: ResourceType);
fetchAll(): Promise<FeedResponse<T>>;
fetchAll(options?: QueryOperationOptions): Promise<FeedResponse<T>>;
// (undocumented)
fetchAllInternal(diagnosticNode: DiagnosticNodeInternal): Promise<FeedResponse<T>>;
fetchNext(): Promise<FeedResponse<T>>;
getAsyncIterator(): AsyncIterable<FeedResponse<T>>;
fetchAllInternal(diagnosticNode: DiagnosticNodeInternal, options?: QueryOperationOptions): Promise<FeedResponse<T>>;
fetchNext(options?: QueryOperationOptions): Promise<FeedResponse<T>>;
getAsyncIterator(options?: QueryOperationOptions): AsyncIterable<FeedResponse<T>>;
hasMoreResults(): boolean;
reset(): void;
}
Expand Down Expand Up @@ -1764,6 +1794,11 @@ export const QueryMetricsConstants: {
SchedulingMetricsText: string;
};

// @public (undocumented)
export interface QueryOperationOptions {
ruCapPerOperation?: number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does ru mean? Can we find a clearer name?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a well known concept for request units in the case of Cosmos DB https://learn.microsoft.com/en-us/azure/cosmos-db/request-units

}

// @public (undocumented)
export class QueryPreparationTimes {
constructor(queryCompilationTime: TimeSpan, logicalPlanBuildTime: TimeSpan, physicalPlanBuildTime: TimeSpan, queryOptimizationTime: TimeSpan);
Expand Down Expand Up @@ -2004,6 +2039,15 @@ export interface RetryOptions {
maxWaitTimeInSeconds: number;
}

// @public (undocumented)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed a bunch of shipped and new undocumented code - is that expected?

export class RUCapPerOperationExceededError extends ErrorResponse {
constructor(message?: string, fetchedResults?: any[]);
// (undocumented)
readonly code: string;
// (undocumented)
fetchedResults: any[];
}

// @public (undocumented)
export class RuntimeExecutionTimes {
constructor(queryEngineExecutionTime: TimeSpan, systemFunctionExecutionTime: TimeSpan, userDefinedFunctionExecutionTime: TimeSpan);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { GeospatialType } from "../../documents/GeospatialType";
import { ChangeFeedPolicy } from "../ChangeFeed/ChangeFeedPolicy";
import { ComputedProperty } from "../../documents/ComputedProperty";
import { VectorEmbeddingPolicy } from "../../documents/VectorEmbeddingPolicy";
import { FullTextPolicy } from "../../documents/FullTextPolicy";

export interface ContainerDefinition {
/** The id of the container. */
Expand All @@ -31,4 +32,6 @@ export interface ContainerDefinition {
computedProperties?: ComputedProperty[];
/** The vector embedding policy information for storing items in a container. */
vectorEmbeddingPolicy?: VectorEmbeddingPolicy;
/** The full text policy information for storing items in a container. */
fullTextPolicy?: FullTextPolicy;
}
37 changes: 37 additions & 0 deletions sdk/cosmosdb/cosmos/src/common/RUConsumedManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import semaphore from "semaphore";

/**
* @hidden
* @hidden
* Specifies Net RUConsumed
*/
export class RUConsumedManager {
private ruConsumed: number = 0;
private semaphore: any;

constructor() {
this.semaphore = semaphore(1);
}

getRUConsumed(): Promise<number> {
return new Promise((resolve) => {
this.semaphore.take(() => {
this.semaphore.leave();
resolve(this.ruConsumed);
});
});
}

addToRUConsumed(value: number): Promise<void> {
return new Promise((resolve) => {
this.semaphore.take(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a semaphore needed for synchronous operations? I thought JavaScript has run-to-completion semantics but maybe I missed something?

this.ruConsumed += value;
this.semaphore.leave();
resolve();
});
});
}
}
6 changes: 4 additions & 2 deletions sdk/cosmosdb/cosmos/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export const Constants = {
AzureNamespace: "Azure.Cosmos",
AzurePackageName: "@azure/cosmos",
SDKName: "azure-cosmos-js",
SDKVersion: "4.1.2",
SDKVersion: "4.2.0-beta.1",

// Diagnostics
CosmosDbDiagnosticLevelEnvVarName: "AZURE_COSMOSDB_DIAGNOSTICS_LEVEL",
Expand Down Expand Up @@ -261,7 +261,7 @@ export const Constants = {
MinimumInclusiveEffectivePartitionKey: "",
MaximumExclusiveEffectivePartitionKey: "FF",
},

NonStreamingQueryDefaultRUThreshold: 5000,
// Changefeed AllVersionsAndDeletesMode formatting version
AllVersionsAndDeletesChangeFeedWireFormatVersion: "2021-09-15",
ChangeFeedIfNoneMatchStartFromNowHeader: "*",
Expand Down Expand Up @@ -491,4 +491,6 @@ export enum QueryFeature {
MultipleAggregates = "MultipleAggregates",
NonStreamingOrderBy = "NonStreamingOrderBy",
ListAndSetAggregate = "ListAndSetAggregate",
CountIf = "CountIf",
HybridSearch = "HybridSearch",
}
1 change: 1 addition & 0 deletions sdk/cosmosdb/cosmos/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./constants";
export * from "./helper";
export * from "./statusCodes";
export * from "./uriFactory";
export { RUConsumedManager } from "./RUConsumedManager";
30 changes: 30 additions & 0 deletions sdk/cosmosdb/cosmos/src/documents/FullTextPolicy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

/**
* Represents a full text policy for a collection in the Azure Cosmos DB service.
*/
export interface FullTextPolicy {
/**
* The default language for the full text .
*/
defaultLanguage: string;
/**
* The paths to be indexed for full text search.
*/
fullTextPaths: FullTextPath[];
}

/**
* Represents a full text path to be indexed in the Azure Cosmos DB service.
*/
export interface FullTextPath {
/**
* The path to be indexed for full text search.
*/
path: string;
/**
* The language for the full text path.
*/
language: string;
}
10 changes: 10 additions & 0 deletions sdk/cosmosdb/cosmos/src/documents/IndexingPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface IndexingPolicy {
vectorIndexes?: VectorIndex[];
/** An array of {@link CompositeIndexes} representing composite indexes to be included. */
compositeIndexes?: CompositePath[][];
/** An array of {@link FullTextIndex} representing full text indexes to be included. */
fullTextIndexes?: FullTextIndex[];
}

/* The target data type of a spatial path */
Expand Down Expand Up @@ -96,3 +98,11 @@ export interface CompositePath {
/** The order of the composite index, either "ascending" or "descending". */
order: "ascending" | "descending";
}

/**
* Represents a full text index in the indexing policy.
*/
export interface FullTextIndex {
/** The path in the JSON document to index. */
path: string;
}
1 change: 1 addition & 0 deletions sdk/cosmosdb/cosmos/src/documents/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from "./UserDefinedFunctionType";
export * from "./GeospatialType";
export * from "./ComputedProperty";
export * from "./VectorEmbeddingPolicy";
export * from "./FullTextPolicy";
3 changes: 3 additions & 0 deletions sdk/cosmosdb/cosmos/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ export {
VectorEmbeddingDataType,
VectorEmbeddingDistanceFunction,
VectorIndexType,
FullTextIndex,
FullTextPolicy,
FullTextPath,
} from "./documents";

export { UniqueKeyPolicy, UniqueKey } from "./client/Container/UniqueKeyPolicy";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { GlobalStatistics } from "../../request/globalStatistics";
import { Aggregator } from "./Aggregator";

export class GlobalStatisticsAggregator implements Aggregator {
private globalStatistics: GlobalStatistics;

constructor() {
this.globalStatistics = {
documentCount: 0,
fullTextStatistics: [],
};
}

public aggregate(other: GlobalStatistics): void {
if (!other) {
return;
}
// Aggregate document count
this.globalStatistics.documentCount += other.documentCount;
// Ensure `fullTextStatistics` is initialized
if (!other.fullTextStatistics || other.fullTextStatistics.length === 0) {
return;
}

// Initialize `this.globalStatistics.fullTextStatistics` if it's empty
if (this.globalStatistics.fullTextStatistics.length === 0) {
this.globalStatistics.fullTextStatistics = other.fullTextStatistics.map((stat) => ({
totalWordCount: stat.totalWordCount,
hitCounts: [...stat.hitCounts],
}));
} else {
// Loop through `other.fullTextStatistics` to add values to `this.globalStatistics.fullTextStatistics`
for (let i = 0; i < other.fullTextStatistics.length; i++) {
const otherStat = other.fullTextStatistics[i];

// Ensure the index `i` is initialized
if (!this.globalStatistics.fullTextStatistics[i]) {
this.globalStatistics.fullTextStatistics[i] = {
totalWordCount: 0,
hitCounts: [],
};
}

// Add totalWordCount
this.globalStatistics.fullTextStatistics[i].totalWordCount += otherStat.totalWordCount;

// Aggregate `hitCounts`
for (let j = 0; j < otherStat.hitCounts.length; j++) {
// Initialize hit count if necessary
if (this.globalStatistics.fullTextStatistics[i].hitCounts.length <= j) {
this.globalStatistics.fullTextStatistics[i].hitCounts.push(0);
}
this.globalStatistics.fullTextStatistics[i].hitCounts[j] += otherStat.hitCounts[j];
}
}
}
}

public getResult(): GlobalStatistics {
return this.globalStatistics;
}
}
Loading