mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 09:20:16 +00:00
Add support for multi-partition key (#1252)
This commit is contained in:
@@ -37,7 +37,8 @@ describe("Collection", () => {
|
||||
version: 2,
|
||||
});
|
||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
||||
expect(collection.partitionKeyProperty).toBe("somePartitionKey.anotherPartitionKey");
|
||||
expect(collection.partitionKeyProperties.length).toBe(1);
|
||||
expect(collection.partitionKeyProperties[0]).toBe("somePartitionKey.anotherPartitionKey");
|
||||
});
|
||||
|
||||
it("should strip out forward slashes from single partition key paths", () => {
|
||||
@@ -47,7 +48,8 @@ describe("Collection", () => {
|
||||
version: 2,
|
||||
});
|
||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
||||
expect(collection.partitionKeyProperty).toBe("somePartitionKey");
|
||||
expect(collection.partitionKeyProperties.length).toBe(1);
|
||||
expect(collection.partitionKeyProperties[0]).toBe("somePartitionKey");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,7 +63,8 @@ describe("Collection", () => {
|
||||
version: 2,
|
||||
});
|
||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
||||
expect(collection.partitionKeyPropertyHeader).toBe("/somePartitionKey/anotherPartitionKey");
|
||||
expect(collection.partitionKeyPropertyHeaders.length).toBe(1);
|
||||
expect(collection.partitionKeyPropertyHeaders[0]).toBe("/somePartitionKey/anotherPartitionKey");
|
||||
});
|
||||
|
||||
it("should preserve forward slash on a single partition key", () => {
|
||||
@@ -71,7 +74,8 @@ describe("Collection", () => {
|
||||
version: 2,
|
||||
});
|
||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
||||
expect(collection.partitionKeyPropertyHeader).toBe("/somePartitionKey");
|
||||
expect(collection.partitionKeyPropertyHeaders.length).toBe(1);
|
||||
expect(collection.partitionKeyPropertyHeaders[0]).toBe("/somePartitionKey");
|
||||
});
|
||||
|
||||
it("should be null if there is no partition key", () => {
|
||||
@@ -81,7 +85,7 @@ describe("Collection", () => {
|
||||
kind: "Hash",
|
||||
});
|
||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
||||
expect(collection.partitionKeyPropertyHeader).toBeNull();
|
||||
expect(collection.partitionKeyPropertyHeaders.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,8 +50,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
public rid: string;
|
||||
public databaseId: string;
|
||||
public partitionKey: DataModels.PartitionKey;
|
||||
public partitionKeyPropertyHeader: string;
|
||||
public partitionKeyProperty: string;
|
||||
public partitionKeyPropertyHeaders: string[];
|
||||
public partitionKeyProperties: string[];
|
||||
public id: ko.Observable<string>;
|
||||
public defaultTtl: ko.Observable<number>;
|
||||
public indexingPolicy: ko.Observable<DataModels.IndexingPolicy>;
|
||||
@@ -120,31 +120,25 @@ export default class Collection implements ViewModels.Collection {
|
||||
this.requestSchema = data.requestSchema;
|
||||
this.geospatialConfig = ko.observable(data.geospatialConfig);
|
||||
|
||||
// TODO fix this to only replace non-excaped single quotes
|
||||
this.partitionKeyProperty =
|
||||
(this.partitionKey &&
|
||||
this.partitionKey.paths &&
|
||||
this.partitionKey.paths.length &&
|
||||
this.partitionKey.paths.length > 0 &&
|
||||
this.partitionKey.paths[0].replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "")) ||
|
||||
null;
|
||||
this.partitionKeyPropertyHeader =
|
||||
(this.partitionKey &&
|
||||
this.partitionKey.paths &&
|
||||
this.partitionKey.paths.length > 0 &&
|
||||
this.partitionKey.paths[0]) ||
|
||||
null;
|
||||
this.partitionKeyPropertyHeaders = this.partitionKey?.paths;
|
||||
this.partitionKeyProperties = this.partitionKeyPropertyHeaders?.map((partitionKeyPropertyHeader, i) => {
|
||||
// TODO fix this to only replace non-excaped single quotes
|
||||
let partitionKeyProperty = partitionKeyPropertyHeader.replace(/[/]+/g, ".").substring(1).replace(/[']+/g, "");
|
||||
|
||||
if (userContext.apiType === "Mongo" && this.partitionKeyProperty && ~this.partitionKeyProperty.indexOf(`"`)) {
|
||||
this.partitionKeyProperty = this.partitionKeyProperty.replace(/["]+/g, "");
|
||||
}
|
||||
if (userContext.apiType === "Mongo" && partitionKeyProperty) {
|
||||
if (~partitionKeyProperty.indexOf(`"`)) {
|
||||
partitionKeyProperty = partitionKeyProperty.replace(/["]+/g, "");
|
||||
}
|
||||
// TODO #10738269 : Add this logic in a derived class for Mongo
|
||||
if (partitionKeyProperty.indexOf("$v") > -1) {
|
||||
// From $v.shard.$v.key.$v > shard.key
|
||||
partitionKeyProperty = partitionKeyProperty.replace(/.\$v/g, "").replace(/\$v./g, "");
|
||||
this.partitionKeyPropertyHeaders[i] = partitionKeyProperty;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO #10738269 : Add this logic in a derived class for Mongo
|
||||
if (userContext.apiType === "Mongo" && this.partitionKeyProperty && this.partitionKeyProperty.indexOf("$v") > -1) {
|
||||
// From $v.shard.$v.key.$v > shard.key
|
||||
this.partitionKeyProperty = this.partitionKeyProperty.replace(/.\$v/g, "").replace(/\$v./g, "");
|
||||
this.partitionKeyPropertyHeader = "/" + this.partitionKeyProperty;
|
||||
}
|
||||
return partitionKeyProperty;
|
||||
});
|
||||
|
||||
this.documentIds = ko.observableArray<DocumentId>([]);
|
||||
this.isCollectionExpanded = ko.observable<boolean>(false);
|
||||
@@ -471,7 +465,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
|
||||
collection: this,
|
||||
masterKey: userContext.masterKey || "",
|
||||
collectionPartitionKeyProperty: this.partitionKeyProperty,
|
||||
collectionPartitionKeyProperty: this.partitionKeyProperties?.[0],
|
||||
collectionId: this.id(),
|
||||
databaseId: this.databaseId,
|
||||
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
||||
@@ -710,7 +704,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
tabPath: "",
|
||||
collection: this,
|
||||
masterKey: userContext.masterKey || "",
|
||||
collectionPartitionKeyProperty: this.partitionKeyProperty,
|
||||
collectionPartitionKeyProperty: this.partitionKeyProperties?.[0],
|
||||
collectionId: this.id(),
|
||||
databaseId: this.databaseId,
|
||||
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
||||
|
||||
@@ -150,7 +150,7 @@ export default class ConflictId {
|
||||
partitionKeyValueResolved
|
||||
);
|
||||
|
||||
documentId.partitionKeyProperty = this.partitionKeyProperty;
|
||||
documentId.partitionKeyProperties = [this.partitionKeyProperty];
|
||||
documentId.partitionKey = this.partitionKey;
|
||||
|
||||
return documentId;
|
||||
|
||||
@@ -9,21 +9,21 @@ export default class DocumentId {
|
||||
public self: string;
|
||||
public ts: string;
|
||||
public id: ko.Observable<string>;
|
||||
public partitionKeyProperty: string;
|
||||
public partitionKeyProperties: string[];
|
||||
public partitionKey: DataModels.PartitionKey;
|
||||
public partitionKeyValue: any;
|
||||
public stringPartitionKeyValue: string;
|
||||
public partitionKeyValue: any[];
|
||||
public stringPartitionKeyValues: string[];
|
||||
public isDirty: ko.Observable<boolean>;
|
||||
|
||||
constructor(container: DocumentsTab, data: any, partitionKeyValue: any) {
|
||||
constructor(container: DocumentsTab, data: any, partitionKeyValue: any[]) {
|
||||
this.container = container;
|
||||
this.self = data._self;
|
||||
this.rid = data._rid;
|
||||
this.ts = data._ts;
|
||||
this.partitionKeyValue = partitionKeyValue;
|
||||
this.partitionKeyProperty = container && container.partitionKeyProperty;
|
||||
this.partitionKeyProperties = container?.partitionKeyProperties;
|
||||
this.partitionKey = container && container.partitionKey;
|
||||
this.stringPartitionKeyValue = this.getPartitionKeyValueAsString();
|
||||
this.stringPartitionKeyValues = this.getPartitionKeyValueAsString();
|
||||
this.id = ko.observable(data.id);
|
||||
this.isDirty = ko.observable(false);
|
||||
}
|
||||
@@ -46,34 +46,35 @@ export default class DocumentId {
|
||||
}
|
||||
|
||||
public partitionKeyHeader(): Object {
|
||||
if (!this.partitionKeyProperty) {
|
||||
if (!this.partitionKeyProperties || this.partitionKeyProperties.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.partitionKeyValue === undefined) {
|
||||
if (!this.partitionKeyValue || this.partitionKeyValue.length === 0) {
|
||||
return [{}];
|
||||
}
|
||||
|
||||
return [this.partitionKeyValue];
|
||||
}
|
||||
|
||||
public getPartitionKeyValueAsString(): string {
|
||||
const partitionKeyValue: any = this.partitionKeyValue;
|
||||
const typeOfPartitionKeyValue: string = typeof partitionKeyValue;
|
||||
public getPartitionKeyValueAsString(): string[] {
|
||||
return this.partitionKeyValue?.map((partitionKeyValue) => {
|
||||
const typeOfPartitionKeyValue: string = typeof partitionKeyValue;
|
||||
|
||||
if (
|
||||
typeOfPartitionKeyValue === "undefined" ||
|
||||
typeOfPartitionKeyValue === "null" ||
|
||||
typeOfPartitionKeyValue === "object"
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
if (
|
||||
typeOfPartitionKeyValue === "undefined" ||
|
||||
typeOfPartitionKeyValue === "null" ||
|
||||
typeOfPartitionKeyValue === "object"
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeOfPartitionKeyValue === "string") {
|
||||
return partitionKeyValue;
|
||||
}
|
||||
if (typeOfPartitionKeyValue === "string") {
|
||||
return partitionKeyValue;
|
||||
}
|
||||
|
||||
return JSON.stringify(partitionKeyValue);
|
||||
return JSON.stringify(partitionKeyValue);
|
||||
});
|
||||
}
|
||||
|
||||
public async loadDocument(): Promise<void> {
|
||||
|
||||
@@ -22,8 +22,8 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
|
||||
public rid: string;
|
||||
public rawDataModel: DataModels.Collection;
|
||||
public partitionKey: DataModels.PartitionKey;
|
||||
public partitionKeyProperty: string;
|
||||
public partitionKeyPropertyHeader: string;
|
||||
public partitionKeyProperties: string[];
|
||||
public partitionKeyPropertyHeaders: string[];
|
||||
public id: ko.Observable<string>;
|
||||
public children: ko.ObservableArray<ViewModels.TreeNode>;
|
||||
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
|
||||
|
||||
Reference in New Issue
Block a user