@azure/cosmos
Version:
Microsoft Azure Cosmos DB Service Node.js SDK for NOSQL API
155 lines (154 loc) • 5.54 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var RidSkipCountFilter_exports = {};
__export(RidSkipCountFilter_exports, {
RidSkipCountFilter: () => RidSkipCountFilter
});
module.exports = __toCommonJS(RidSkipCountFilter_exports);
var import_orderByComparator = require("../orderByComparator.js");
class RidSkipCountFilter {
/**
* @param filterContext - The context containing values from the continuation token.
*/
constructor(filterContext) {
this.filterContext = filterContext;
this.remainingSkipCount = this.filterContext.skipCount;
}
remainingSkipCount;
/**
* Applies the comprehensive OrderBy + RID + SkipCount filtering logic.
* @param documents - The documents fetched from the target partition.
* @returns A new array containing only the documents that should be processed.
*/
applyFilter(documents) {
const filteredDocs = [];
let skippedCount = 0;
for (const doc of documents) {
if (!this.shouldIncludeDocument(doc)) {
skippedCount++;
continue;
}
filteredDocs.push(doc);
}
return filteredDocs;
}
/**
* Determines if a document should be included based on OrderBy values, RID, and skip count.
* Implements the .NET SDK's FilterNextAsync logic with robust OrderBy comparison.
*/
shouldIncludeDocument(doc) {
const sortOrderCompare = this.compareOrderByItems(doc);
if (sortOrderCompare < 0) {
return true;
}
if (sortOrderCompare > 0) {
return false;
}
const docRid = doc._rid;
let ridOrderCompare;
if (this.filterContext.rid === docRid) {
ridOrderCompare = 0;
} else {
const continuationBigInt = this.ridToBigInt(this.filterContext.rid);
const docBigInt = this.ridToBigInt(docRid);
if (continuationBigInt < docBigInt) {
ridOrderCompare = -1;
} else if (continuationBigInt > docBigInt) {
ridOrderCompare = 1;
} else {
ridOrderCompare = 0;
}
}
const sortOrders = this.filterContext.sortOrders || [];
const queryExecutionInfo = this.filterContext.queryExecutionInfo;
const hasDescendingSort = sortOrders.some((order) => order === "Descending");
if (!queryExecutionInfo || queryExecutionInfo.reverseRidEnabled) {
if (hasDescendingSort) {
ridOrderCompare = -ridOrderCompare;
}
} else {
if (queryExecutionInfo.reverseIndexScan) {
ridOrderCompare = -ridOrderCompare;
}
}
if (ridOrderCompare > 0) {
return false;
}
if (ridOrderCompare < 0) {
return true;
}
if (this.remainingSkipCount > 0) {
this.remainingSkipCount--;
return false;
}
return true;
}
/**
* Convert RID to BigInt for accurate comparison.
* Decodes base64 RID and extracts the Document ID portion (8 bytes at offset 8) as BigInt.
*
* RID Structure (from Java SDK ResourceId.java):
* - Bytes 0-3: Database ID (4 bytes)
* - Bytes 4-7: Collection ID (4 bytes)
* - Bytes 8-15: Document ID (8 bytes, stored in Big Endian but compared in Little Endian)
* - Bytes 16-19: Attachment ID (4 bytes, optional)
*/
ridToBigInt(rid) {
if (rid === null || rid === void 0) {
throw new Error(`RID is null or undefined`);
}
if (typeof rid !== "string") {
throw new Error(`RID must be a string, got ${typeof rid}`);
}
if (rid.trim().length === 0) {
throw new Error(`RID is empty string`);
}
try {
const normalizedRid = rid.replace(/-/g, "/");
const bytes = Buffer.from(normalizedRid, "base64");
if (bytes.length < 16) {
throw new Error(`RID too short: expected at least 16 bytes, got ${bytes.length}`);
}
let result = 0n;
for (let i = 15; i >= 8; i--) {
result = result << 8n | BigInt(bytes[i] & 255);
}
return result;
} catch (error) {
throw new Error(
`Failed to convert RID '${rid}' to BigInt: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Compares the OrderBy items of a document with the continuation token's OrderBy items.
* Uses the exported compareOrderByItems utility function from orderByItemComparator.
* @param doc - The document to compare
* @returns negative if doc comes before continuation, 0 if same, positive if doc comes after
*/
compareOrderByItems(doc) {
const docOrderByItems = doc.orderByItems || [];
const continuationOrderByItems = this.filterContext.orderByItems || [];
const sortOrders = this.filterContext.sortOrders || [];
return (0, import_orderByComparator.compareOrderByItems)(docOrderByItems, continuationOrderByItems, sortOrders);
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
RidSkipCountFilter
});