Add support for multi-partition key (#1252)
This commit is contained in:
parent
9e7bbcfab6
commit
22f7d588a1
|
@ -25,12 +25,12 @@ const fetchMock = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const partitionKeyProperty = "pk";
|
const partitionKeyProperties = ["pk"];
|
||||||
|
|
||||||
const collection = {
|
const collection = {
|
||||||
id: () => "testCollection",
|
id: () => "testCollection",
|
||||||
rid: "testCollectionrid",
|
rid: "testCollectionrid",
|
||||||
partitionKeyProperty,
|
partitionKeyProperties,
|
||||||
partitionKey: {
|
partitionKey: {
|
||||||
paths: ["/pk"],
|
paths: ["/pk"],
|
||||||
kind: "Hash",
|
kind: "Hash",
|
||||||
|
@ -41,7 +41,7 @@ const collection = {
|
||||||
const documentId = ({
|
const documentId = ({
|
||||||
partitionKeyHeader: () => "[]",
|
partitionKeyHeader: () => "[]",
|
||||||
self: "db/testDB/db/testCollection/docs/testId",
|
self: "db/testDB/db/testCollection/docs/testId",
|
||||||
partitionKeyProperty,
|
partitionKeyProperties,
|
||||||
partitionKey: {
|
partitionKey: {
|
||||||
paths: ["/pk"],
|
paths: ["/pk"],
|
||||||
kind: "Hash",
|
kind: "Hash",
|
||||||
|
|
|
@ -76,7 +76,7 @@ export function queryDocuments(
|
||||||
dba: databaseAccount.name,
|
dba: databaseAccount.name,
|
||||||
pk:
|
pk:
|
||||||
collection && collection.partitionKey && !collection.partitionKey.systemKey
|
collection && collection.partitionKey && !collection.partitionKey.systemKey
|
||||||
? collection.partitionKeyProperty
|
? collection.partitionKeyProperties?.[0]
|
||||||
: "",
|
: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ export function readDocument(
|
||||||
dba: databaseAccount.name,
|
dba: databaseAccount.name,
|
||||||
pk:
|
pk:
|
||||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||||
? documentId.partitionKeyProperty
|
? documentId.partitionKeyProperties?.[0]
|
||||||
: "",
|
: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ export function updateDocument(
|
||||||
dba: databaseAccount.name,
|
dba: databaseAccount.name,
|
||||||
pk:
|
pk:
|
||||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||||
? documentId.partitionKeyProperty
|
? documentId.partitionKeyProperties?.[0]
|
||||||
: "",
|
: "",
|
||||||
};
|
};
|
||||||
const endpoint = getFeatureEndpointOrDefault("updateDocument");
|
const endpoint = getFeatureEndpointOrDefault("updateDocument");
|
||||||
|
@ -266,7 +266,7 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
|
||||||
dba: databaseAccount.name,
|
dba: databaseAccount.name,
|
||||||
pk:
|
pk:
|
||||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||||
? documentId.partitionKeyProperty
|
? documentId.partitionKeyProperties?.[0]
|
||||||
: "",
|
: "",
|
||||||
};
|
};
|
||||||
const endpoint = getFeatureEndpointOrDefault("deleteDocument");
|
const endpoint = getFeatureEndpointOrDefault("deleteDocument");
|
||||||
|
|
|
@ -149,10 +149,10 @@ export class QueriesClient {
|
||||||
const documentId = new DocumentId(
|
const documentId = new DocumentId(
|
||||||
{
|
{
|
||||||
partitionKey: QueriesClient.PartitionKey,
|
partitionKey: QueriesClient.PartitionKey,
|
||||||
partitionKeyProperty: "id",
|
partitionKeyProperties: ["id"],
|
||||||
} as DocumentsTab,
|
} as DocumentsTab,
|
||||||
query,
|
query,
|
||||||
query.queryName
|
[query.queryName]
|
||||||
); // TODO: Remove DocumentId's dependency on DocumentsTab
|
); // TODO: Remove DocumentId's dependency on DocumentsTab
|
||||||
const options: any = { partitionKey: query.resourceId };
|
const options: any = { partitionKey: query.resourceId };
|
||||||
return deleteDocument(queriesCollection, documentId)
|
return deleteDocument(queriesCollection, documentId)
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
import { Item } from "@azure/cosmos";
|
import { Item, RequestOptions } from "@azure/cosmos";
|
||||||
import { CollectionBase } from "../../Contracts/ViewModels";
|
import { CollectionBase } from "../../Contracts/ViewModels";
|
||||||
|
import DocumentId from "../../Explorer/Tree/DocumentId";
|
||||||
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
|
import { HttpHeaders } from "../Constants";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { getEntityName } from "../DocumentUtility";
|
import { getEntityName } from "../DocumentUtility";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import DocumentId from "../../Explorer/Tree/DocumentId";
|
|
||||||
|
|
||||||
export const readDocument = async (collection: CollectionBase, documentId: DocumentId): Promise<Item> => {
|
export const readDocument = async (collection: CollectionBase, documentId: DocumentId): Promise<Item> => {
|
||||||
const entityName = getEntityName();
|
const entityName = getEntityName();
|
||||||
const clearMessage = logConsoleProgress(`Reading ${entityName} ${documentId.id()}`);
|
const clearMessage = logConsoleProgress(`Reading ${entityName} ${documentId.id()}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const options: RequestOptions =
|
||||||
|
documentId.partitionKey.kind === "MultiHash"
|
||||||
|
? {
|
||||||
|
[HttpHeaders.partitionKey]: documentId.partitionKeyValue,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
const response = await client()
|
const response = await client()
|
||||||
.database(collection.databaseId)
|
.database(collection.databaseId)
|
||||||
.container(collection.id())
|
.container(collection.id())
|
||||||
.item(documentId.id(), documentId.partitionKeyValue)
|
.item(documentId.id(), documentId.partitionKeyValue)
|
||||||
.read();
|
.read(options);
|
||||||
|
|
||||||
return response?.resource;
|
return response?.resource;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import { Item, RequestOptions } from "@azure/cosmos";
|
||||||
|
import { HttpHeaders } from "Common/Constants";
|
||||||
import { CollectionBase } from "../../Contracts/ViewModels";
|
import { CollectionBase } from "../../Contracts/ViewModels";
|
||||||
import { Item } from "@azure/cosmos";
|
import DocumentId from "../../Explorer/Tree/DocumentId";
|
||||||
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { client } from "../CosmosClient";
|
import { client } from "../CosmosClient";
|
||||||
import { getEntityName } from "../DocumentUtility";
|
import { getEntityName } from "../DocumentUtility";
|
||||||
import { handleError } from "../ErrorHandlingUtils";
|
import { handleError } from "../ErrorHandlingUtils";
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import DocumentId from "../../Explorer/Tree/DocumentId";
|
|
||||||
|
|
||||||
export const updateDocument = async (
|
export const updateDocument = async (
|
||||||
collection: CollectionBase,
|
collection: CollectionBase,
|
||||||
|
@ -15,11 +16,17 @@ export const updateDocument = async (
|
||||||
const clearMessage = logConsoleProgress(`Updating ${entityName} ${documentId.id()}`);
|
const clearMessage = logConsoleProgress(`Updating ${entityName} ${documentId.id()}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const options: RequestOptions =
|
||||||
|
documentId.partitionKey.kind === "MultiHash"
|
||||||
|
? {
|
||||||
|
[HttpHeaders.partitionKey]: documentId.partitionKeyValue,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
const response = await client()
|
const response = await client()
|
||||||
.database(collection.databaseId)
|
.database(collection.databaseId)
|
||||||
.container(collection.id())
|
.container(collection.id())
|
||||||
.item(documentId.id(), documentId.partitionKeyValue)
|
.item(documentId.id(), documentId.partitionKeyValue)
|
||||||
.replace(newDocument);
|
.replace(newDocument, options);
|
||||||
|
|
||||||
logConsoleInfo(`Successfully updated ${entityName} ${documentId.id()}`);
|
logConsoleInfo(`Successfully updated ${entityName} ${documentId.id()}`);
|
||||||
return response?.resource;
|
return response?.resource;
|
||||||
|
|
|
@ -106,8 +106,8 @@ export interface CollectionBase extends TreeNode {
|
||||||
self: string;
|
self: string;
|
||||||
rawDataModel: DataModels.Collection;
|
rawDataModel: DataModels.Collection;
|
||||||
partitionKey: DataModels.PartitionKey;
|
partitionKey: DataModels.PartitionKey;
|
||||||
partitionKeyProperty: string;
|
partitionKeyProperties: string[];
|
||||||
partitionKeyPropertyHeader: string;
|
partitionKeyPropertyHeaders: string[];
|
||||||
id: ko.Observable<string>;
|
id: ko.Observable<string>;
|
||||||
selectedSubnodeKind: ko.Observable<CollectionTabKind>;
|
selectedSubnodeKind: ko.Observable<CollectionTabKind>;
|
||||||
children: ko.ObservableArray<TreeNode>;
|
children: ko.ObservableArray<TreeNode>;
|
||||||
|
|
|
@ -65,8 +65,8 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
|
||||||
constructor(props: SubSettingsComponentProps) {
|
constructor(props: SubSettingsComponentProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.geospatialVisible = userContext.apiType === "SQL";
|
this.geospatialVisible = userContext.apiType === "SQL";
|
||||||
this.partitionKeyValue = "/" + this.props.collection.partitionKeyProperty;
|
|
||||||
this.partitionKeyName = userContext.apiType === "Mongo" ? "Shard key" : "Partition key";
|
this.partitionKeyName = userContext.apiType === "Mongo" ? "Shard key" : "Partition key";
|
||||||
|
this.partitionKeyValue = this.getPartitionKeyValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
|
@ -291,6 +291,14 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private getPartitionKeyValue = (): string => {
|
||||||
|
if (userContext.apiType === "Mongo") {
|
||||||
|
return this.props.collection.partitionKeyProperties?.[0] || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this.props.collection.partitionKeyProperties || []).map((property) => "/" + property).join(", ");
|
||||||
|
};
|
||||||
|
|
||||||
private getPartitionKeyComponent = (): JSX.Element => (
|
private getPartitionKeyComponent = (): JSX.Element => (
|
||||||
<Stack {...titleAndInputStackProps}>
|
<Stack {...titleAndInputStackProps}>
|
||||||
{this.getPartitionKeyVisible() && (
|
{this.getPartitionKeyVisible() && (
|
||||||
|
@ -310,7 +318,8 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
|
||||||
if (
|
if (
|
||||||
userContext.apiType === "Cassandra" ||
|
userContext.apiType === "Cassandra" ||
|
||||||
userContext.apiType === "Tables" ||
|
userContext.apiType === "Tables" ||
|
||||||
!this.props.collection.partitionKeyProperty ||
|
!this.props.collection.partitionKeyProperties ||
|
||||||
|
this.props.collection.partitionKeyProperties.length === 0 ||
|
||||||
(userContext.apiType === "Mongo" && this.props.collection.partitionKey.systemKey)
|
(userContext.apiType === "Mongo" && this.props.collection.partitionKey.systemKey)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const collection = ({
|
||||||
kind: "hash",
|
kind: "hash",
|
||||||
version: 2,
|
version: 2,
|
||||||
},
|
},
|
||||||
partitionKeyProperty: "partitionKey",
|
partitionKeyProperties: ["partitionKey"],
|
||||||
readSettings: () => {
|
readSettings: () => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1669,7 +1669,9 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"paths": Array [],
|
"paths": Array [],
|
||||||
"version": 2,
|
"version": 2,
|
||||||
},
|
},
|
||||||
"partitionKeyProperty": "partitionKey",
|
"partitionKeyProperties": Array [
|
||||||
|
"partitionKey",
|
||||||
|
],
|
||||||
"readSettings": [Function],
|
"readSettings": [Function],
|
||||||
"uniqueKeyPolicy": Object {},
|
"uniqueKeyPolicy": Object {},
|
||||||
"usageSizeInKB": [Function],
|
"usageSizeInKB": [Function],
|
||||||
|
@ -3348,7 +3350,9 @@ exports[`SettingsComponent renders 1`] = `
|
||||||
"paths": Array [],
|
"paths": Array [],
|
||||||
"version": 2,
|
"version": 2,
|
||||||
},
|
},
|
||||||
"partitionKeyProperty": "partitionKey",
|
"partitionKeyProperties": Array [
|
||||||
|
"partitionKey",
|
||||||
|
],
|
||||||
"readSettings": [Function],
|
"readSettings": [Function],
|
||||||
"uniqueKeyPolicy": Object {},
|
"uniqueKeyPolicy": Object {},
|
||||||
"usageSizeInKB": [Function],
|
"usageSizeInKB": [Function],
|
||||||
|
|
|
@ -8,23 +8,23 @@ import { CassandraAddCollectionPane } from "../Panes/CassandraAddCollectionPane/
|
||||||
import { SettingsPane } from "../Panes/SettingsPane/SettingsPane";
|
import { SettingsPane } from "../Panes/SettingsPane/SettingsPane";
|
||||||
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
||||||
|
|
||||||
function generateQueryText(action: ActionContracts.OpenQueryTab, partitionKeyProperty: string): string {
|
function generateQueryText(action: ActionContracts.OpenQueryTab, partitionKeyProperties: string[]): string {
|
||||||
if (!action.query) {
|
if (!action.query) {
|
||||||
return "SELECT * FROM c";
|
return "SELECT * FROM c";
|
||||||
} else if (action.query.text) {
|
} else if (action.query.text) {
|
||||||
return action.query.text;
|
return action.query.text;
|
||||||
} else if (!!action.query.partitionKeys && action.query.partitionKeys.length > 0) {
|
} else if (action.query.partitionKeys?.length > 0 && partitionKeyProperties?.length > 0) {
|
||||||
let query = "SELECT * FROM c WHERE";
|
let query = "SELECT * FROM c WHERE";
|
||||||
for (let i = 0; i < action.query.partitionKeys.length; i++) {
|
for (let i = 0; i < action.query.partitionKeys.length; i++) {
|
||||||
const partitionKey = action.query.partitionKeys[i];
|
const partitionKey = action.query.partitionKeys[i];
|
||||||
if (!partitionKey) {
|
if (!partitionKey) {
|
||||||
// null partition key case
|
// null partition key case
|
||||||
query = query.concat(` c.${partitionKeyProperty} = ${action.query.partitionKeys[i]}`);
|
query = query.concat(` c.${partitionKeyProperties[i]} = ${action.query.partitionKeys[i]}`);
|
||||||
} else if (typeof partitionKey !== "string") {
|
} else if (typeof partitionKey !== "string") {
|
||||||
// Undefined partition key case
|
// Undefined partition key case
|
||||||
query = query.concat(` NOT IS_DEFINED(c.${partitionKeyProperty})`);
|
query = query.concat(` NOT IS_DEFINED(c.${partitionKeyProperties[i]})`);
|
||||||
} else {
|
} else {
|
||||||
query = query.concat(` c.${partitionKeyProperty} = "${action.query.partitionKeys[i]}"`);
|
query = query.concat(` c.${partitionKeyProperties[i]} = "${action.query.partitionKeys[i]}"`);
|
||||||
}
|
}
|
||||||
if (i !== action.query.partitionKeys.length - 1) {
|
if (i !== action.query.partitionKeys.length - 1) {
|
||||||
query = query.concat(" OR");
|
query = query.concat(" OR");
|
||||||
|
@ -109,7 +109,7 @@ function openCollectionTab(
|
||||||
collection.onNewQueryClick(
|
collection.onNewQueryClick(
|
||||||
collection,
|
collection,
|
||||||
undefined,
|
undefined,
|
||||||
generateQueryText(action as ActionContracts.OpenQueryTab, collection.partitionKeyProperty)
|
generateQueryText(action as ActionContracts.OpenQueryTab, collection.partitionKeyProperties)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ export function convertEntitiesToDocuments(
|
||||||
};
|
};
|
||||||
if (collection.partitionKey) {
|
if (collection.partitionKey) {
|
||||||
document["partitionKey"] = collection.partitionKey;
|
document["partitionKey"] = collection.partitionKey;
|
||||||
document[collection.partitionKeyProperty] = entity.PartitionKey._;
|
document[collection.partitionKeyProperties[0]] = entity.PartitionKey._;
|
||||||
document["partitionKeyValue"] = entity.PartitionKey._;
|
document["partitionKeyValue"] = entity.PartitionKey._;
|
||||||
}
|
}
|
||||||
for (var property in entity) {
|
for (var property in entity) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default class ConflictsTab extends TabsBase {
|
||||||
this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey);
|
this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey);
|
||||||
this.conflictIds = options.conflictIds;
|
this.conflictIds = options.conflictIds;
|
||||||
this.partitionKeyPropertyHeader =
|
this.partitionKeyPropertyHeader =
|
||||||
(this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader();
|
this.collection?.partitionKeyPropertyHeaders?.[0] || this._getPartitionKeyPropertyHeader();
|
||||||
this.partitionKeyProperty = !!this.partitionKeyPropertyHeader
|
this.partitionKeyProperty = !!this.partitionKeyPropertyHeader
|
||||||
? this.partitionKeyPropertyHeader.replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "")
|
? this.partitionKeyPropertyHeader.replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "")
|
||||||
: null;
|
: null;
|
||||||
|
|
|
@ -143,16 +143,18 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th class="documentsGridHeader" data-bind="text: idHeader" tabindex="0"></th>
|
<th class="documentsGridHeader" data-bind="text: idHeader" tabindex="0"></th>
|
||||||
<!-- ko if: showPartitionKey -->
|
<!-- ko if: showPartitionKey -->
|
||||||
|
<!-- ko foreach: partitionKeyPropertyHeaders -->
|
||||||
<th
|
<th
|
||||||
class="documentsGridHeader documentsGridPartition evenlySpacedHeader"
|
class="documentsGridHeader documentsGridPartition evenlySpacedHeader"
|
||||||
data-bind="
|
data-bind="
|
||||||
attr: {
|
attr: {
|
||||||
title: partitionKeyPropertyHeader
|
title: $data
|
||||||
},
|
},
|
||||||
text: partitionKeyPropertyHeader"
|
text: $data"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
></th>
|
></th>
|
||||||
<!-- /ko -->
|
<!-- /ko -->
|
||||||
|
<!-- /ko -->
|
||||||
<th
|
<th
|
||||||
class="refreshColHeader"
|
class="refreshColHeader"
|
||||||
role="button"
|
role="button"
|
||||||
|
@ -182,13 +184,13 @@
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<td class="tabdocumentsGridElement"><a data-bind="text: $data.id, attr: { title: $data.id }"></a></td>
|
<td class="tabdocumentsGridElement"><a data-bind="text: $data.id, attr: { title: $data.id }"></a></td>
|
||||||
<!-- ko if: $data.partitionKeyProperty -->
|
<!-- ko if: $data.partitionKeyProperties -->
|
||||||
<td class="tabdocumentsGridElement" colspan="2">
|
<!-- ko foreach: $data.stringPartitionKeyValues -->
|
||||||
<a
|
<td class="tabdocumentsGridElement" data-bind="colspan: $parent.stringPartitionKeyValues.length + 1">
|
||||||
data-bind="text: $data.stringPartitionKeyValue, attr: { title: $data.stringPartitionKeyValue }"
|
<a data-bind="text: $data, attr: { title: $data }"></a>
|
||||||
></a>
|
|
||||||
</td>
|
</td>
|
||||||
<!-- /ko -->
|
<!-- /ko -->
|
||||||
|
<!-- /ko -->
|
||||||
</tr>
|
</tr>
|
||||||
<!-- /ko -->
|
<!-- /ko -->
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -50,7 +50,7 @@ export default class DocumentsTab extends TabsBase {
|
||||||
public editorState: ko.Observable<ViewModels.DocumentExplorerState>;
|
public editorState: ko.Observable<ViewModels.DocumentExplorerState>;
|
||||||
public newDocumentButton: ViewModels.Button;
|
public newDocumentButton: ViewModels.Button;
|
||||||
public saveNewDocumentButton: ViewModels.Button;
|
public saveNewDocumentButton: ViewModels.Button;
|
||||||
public saveExisitingDocumentButton: ViewModels.Button;
|
public saveExistingDocumentButton: ViewModels.Button;
|
||||||
public discardNewDocumentChangesButton: ViewModels.Button;
|
public discardNewDocumentChangesButton: ViewModels.Button;
|
||||||
public discardExisitingDocumentChangesButton: ViewModels.Button;
|
public discardExisitingDocumentChangesButton: ViewModels.Button;
|
||||||
public deleteExisitingDocumentButton: ViewModels.Button;
|
public deleteExisitingDocumentButton: ViewModels.Button;
|
||||||
|
@ -65,8 +65,8 @@ export default class DocumentsTab extends TabsBase {
|
||||||
|
|
||||||
// TODO need to refactor
|
// TODO need to refactor
|
||||||
public partitionKey: DataModels.PartitionKey;
|
public partitionKey: DataModels.PartitionKey;
|
||||||
public partitionKeyPropertyHeader: string;
|
public partitionKeyPropertyHeaders: string[];
|
||||||
public partitionKeyProperty: string;
|
public partitionKeyProperties: string[];
|
||||||
public documentIds: ko.ObservableArray<DocumentId>;
|
public documentIds: ko.ObservableArray<DocumentId>;
|
||||||
|
|
||||||
private _documentsIterator: QueryIterator<ItemDefinition & Resource>;
|
private _documentsIterator: QueryIterator<ItemDefinition & Resource>;
|
||||||
|
@ -90,11 +90,10 @@ export default class DocumentsTab extends TabsBase {
|
||||||
this._resourceTokenPartitionKey = options.resourceTokenPartitionKey;
|
this._resourceTokenPartitionKey = options.resourceTokenPartitionKey;
|
||||||
this.documentIds = options.documentIds;
|
this.documentIds = options.documentIds;
|
||||||
|
|
||||||
this.partitionKeyPropertyHeader =
|
this.partitionKeyPropertyHeaders = this.collection?.partitionKeyPropertyHeaders || this.partitionKey?.paths;
|
||||||
(this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader();
|
this.partitionKeyProperties = this.partitionKeyPropertyHeaders?.map((partitionKeyPropertyHeader) =>
|
||||||
this.partitionKeyProperty = !!this.partitionKeyPropertyHeader
|
partitionKeyPropertyHeader.replace(/[/]+/g, ".").substring(1).replace(/[']+/g, "")
|
||||||
? this.partitionKeyPropertyHeader.replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "")
|
);
|
||||||
: null;
|
|
||||||
|
|
||||||
this.isFilterExpanded = ko.observable<boolean>(false);
|
this.isFilterExpanded = ko.observable<boolean>(false);
|
||||||
this.isFilterCreated = ko.observable<boolean>(true);
|
this.isFilterCreated = ko.observable<boolean>(true);
|
||||||
|
@ -227,7 +226,7 @@ export default class DocumentsTab extends TabsBase {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.saveExisitingDocumentButton = {
|
this.saveExistingDocumentButton = {
|
||||||
enabled: ko.computed<boolean>(() => {
|
enabled: ko.computed<boolean>(() => {
|
||||||
switch (this.editorState()) {
|
switch (this.editorState()) {
|
||||||
case ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid:
|
case ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid:
|
||||||
|
@ -445,8 +444,7 @@ export default class DocumentsTab extends TabsBase {
|
||||||
savedDocument,
|
savedDocument,
|
||||||
this.partitionKey as PartitionKeyDefinition
|
this.partitionKey as PartitionKeyDefinition
|
||||||
);
|
);
|
||||||
const partitionKeyValue = partitionKeyValueArray && partitionKeyValueArray[0];
|
let id = new DocumentId(this, savedDocument, partitionKeyValueArray);
|
||||||
let id = new DocumentId(this, savedDocument, partitionKeyValue);
|
|
||||||
let ids = this.documentIds();
|
let ids = this.documentIds();
|
||||||
ids.push(id);
|
ids.push(id);
|
||||||
|
|
||||||
|
@ -489,14 +487,12 @@ export default class DocumentsTab extends TabsBase {
|
||||||
return Q();
|
return Q();
|
||||||
};
|
};
|
||||||
|
|
||||||
public onSaveExisitingDocumentClick = (): Promise<any> => {
|
public onSaveExistingDocumentClick = (): Promise<any> => {
|
||||||
const selectedDocumentId = this.selectedDocumentId();
|
const selectedDocumentId = this.selectedDocumentId();
|
||||||
const documentContent = JSON.parse(this.selectedDocumentContent());
|
const documentContent = JSON.parse(this.selectedDocumentContent());
|
||||||
|
|
||||||
const partitionKeyValueArray = extractPartitionKey(documentContent, this.partitionKey as PartitionKeyDefinition);
|
const partitionKeyValueArray = extractPartitionKey(documentContent, this.partitionKey as PartitionKeyDefinition);
|
||||||
const partitionKeyValue = partitionKeyValueArray && partitionKeyValueArray[0];
|
selectedDocumentId.partitionKeyValue = partitionKeyValueArray;
|
||||||
|
|
||||||
selectedDocumentId.partitionKeyValue = partitionKeyValue;
|
|
||||||
|
|
||||||
this.isExecutionError(false);
|
this.isExecutionError(false);
|
||||||
const startKey: number = TelemetryProcessor.traceStart(Action.UpdateDocument, {
|
const startKey: number = TelemetryProcessor.traceStart(Action.UpdateDocument, {
|
||||||
|
@ -800,7 +796,7 @@ export default class DocumentsTab extends TabsBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public buildQuery(filter: string): string {
|
public buildQuery(filter: string): string {
|
||||||
return QueryUtils.buildDocumentsQuery(filter, this.partitionKeyProperty, this.partitionKey);
|
return QueryUtils.buildDocumentsQuery(filter, this.partitionKeyProperties, this.partitionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getTabsButtons(): CommandButtonComponentProps[] {
|
protected getTabsButtons(): CommandButtonComponentProps[] {
|
||||||
|
@ -844,16 +840,16 @@ export default class DocumentsTab extends TabsBase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.saveExisitingDocumentButton.visible()) {
|
if (this.saveExistingDocumentButton.visible()) {
|
||||||
const label = "Update";
|
const label = "Update";
|
||||||
buttons.push({
|
buttons.push({
|
||||||
iconSrc: SaveIcon,
|
iconSrc: SaveIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
onCommandClick: this.onSaveExisitingDocumentClick,
|
onCommandClick: this.onSaveExistingDocumentClick,
|
||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: !this.saveExisitingDocumentButton.enabled(),
|
disabled: !this.saveExistingDocumentButton.enabled(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,8 +895,8 @@ export default class DocumentsTab extends TabsBase {
|
||||||
this.saveNewDocumentButton.enabled,
|
this.saveNewDocumentButton.enabled,
|
||||||
this.discardNewDocumentChangesButton.visible,
|
this.discardNewDocumentChangesButton.visible,
|
||||||
this.discardNewDocumentChangesButton.enabled,
|
this.discardNewDocumentChangesButton.enabled,
|
||||||
this.saveExisitingDocumentButton.visible,
|
this.saveExistingDocumentButton.visible,
|
||||||
this.saveExisitingDocumentButton.enabled,
|
this.saveExistingDocumentButton.enabled,
|
||||||
this.discardExisitingDocumentChangesButton.visible,
|
this.discardExisitingDocumentChangesButton.visible,
|
||||||
this.discardExisitingDocumentChangesButton.enabled,
|
this.discardExisitingDocumentChangesButton.enabled,
|
||||||
this.deleteExisitingDocumentButton.visible,
|
this.deleteExisitingDocumentButton.visible,
|
||||||
|
@ -910,16 +906,6 @@ export default class DocumentsTab extends TabsBase {
|
||||||
this.updateNavbarWithTabsButtons();
|
this.updateNavbarWithTabsButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getPartitionKeyPropertyHeader(): string {
|
|
||||||
return (
|
|
||||||
(this.partitionKey &&
|
|
||||||
this.partitionKey.paths &&
|
|
||||||
this.partitionKey.paths.length > 0 &&
|
|
||||||
this.partitionKey.paths[0]) ||
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static _createUploadButton(container: Explorer): CommandButtonComponentProps {
|
public static _createUploadButton(container: Explorer): CommandButtonComponentProps {
|
||||||
const label = "Upload Item";
|
const label = "Upload Item";
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -29,15 +29,19 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
super(options);
|
super(options);
|
||||||
this.lastFilterContents = ko.observableArray<string>(['{"id":"foo"}', "{ qty: { $gte: 20 } }"]);
|
this.lastFilterContents = ko.observableArray<string>(['{"id":"foo"}', "{ qty: { $gte: 20 } }"]);
|
||||||
|
|
||||||
if (this.partitionKeyProperty && ~this.partitionKeyProperty.indexOf(`"`)) {
|
this.partitionKeyProperties = this.partitionKeyProperties?.map((partitionKeyProperty, i) => {
|
||||||
this.partitionKeyProperty = this.partitionKeyProperty.replace(/["]+/g, "");
|
if (partitionKeyProperty && ~partitionKeyProperty.indexOf(`"`)) {
|
||||||
}
|
partitionKeyProperty = partitionKeyProperty.replace(/["]+/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
if (this.partitionKeyProperty && this.partitionKeyProperty.indexOf("$v") > -1) {
|
if (partitionKeyProperty && partitionKeyProperty.indexOf("$v") > -1) {
|
||||||
// From $v.shard.$v.key.$v > shard.key
|
// From $v.shard.$v.key.$v > shard.key
|
||||||
this.partitionKeyProperty = this.partitionKeyProperty.replace(/.\$v/g, "").replace(/\$v./g, "");
|
partitionKeyProperty = partitionKeyProperty.replace(/.\$v/g, "").replace(/\$v./g, "");
|
||||||
this.partitionKeyPropertyHeader = "/" + this.partitionKeyProperty;
|
this.partitionKeyPropertyHeaders[i] = "/" + partitionKeyProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return partitionKeyProperty;
|
||||||
|
});
|
||||||
|
|
||||||
this.isFilterExpanded = ko.observable<boolean>(true);
|
this.isFilterExpanded = ko.observable<boolean>(true);
|
||||||
super.buildCommandBarOptions.bind(this);
|
super.buildCommandBarOptions.bind(this);
|
||||||
|
@ -52,12 +56,9 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
tabTitle: this.tabTitle(),
|
tabTitle: this.tabTitle(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
const partitionKeyProperty = this.partitionKeyProperties?.[0];
|
||||||
this.partitionKeyProperty &&
|
if (partitionKeyProperty !== "_id" && !this._hasShardKeySpecified(documentContent)) {
|
||||||
this.partitionKeyProperty !== "_id" &&
|
const message = `The document is lacking the shard property: ${partitionKeyProperty}`;
|
||||||
!this._hasShardKeySpecified(documentContent)
|
|
||||||
) {
|
|
||||||
const message = `The document is lacking the shard property: ${this.partitionKeyProperty}`;
|
|
||||||
this.displayedError(message);
|
this.displayedError(message);
|
||||||
let that = this;
|
let that = this;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -79,7 +80,12 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
|
|
||||||
this.isExecutionError(false);
|
this.isExecutionError(false);
|
||||||
this.isExecuting(true);
|
this.isExecuting(true);
|
||||||
return createDocument(this.collection.databaseId, this.collection, this.partitionKeyProperty, documentContent)
|
return createDocument(
|
||||||
|
this.collection.databaseId,
|
||||||
|
this.collection,
|
||||||
|
this.partitionKeyProperties?.[0],
|
||||||
|
documentContent
|
||||||
|
)
|
||||||
.then(
|
.then(
|
||||||
(savedDocument: any) => {
|
(savedDocument: any) => {
|
||||||
let partitionKeyArray = extractPartitionKey(
|
let partitionKeyArray = extractPartitionKey(
|
||||||
|
@ -87,9 +93,7 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
this._getPartitionKeyDefinition() as PartitionKeyDefinition
|
this._getPartitionKeyDefinition() as PartitionKeyDefinition
|
||||||
);
|
);
|
||||||
|
|
||||||
let partitionKeyValue = partitionKeyArray && partitionKeyArray[0];
|
let id = new ObjectId(this, savedDocument, partitionKeyArray);
|
||||||
|
|
||||||
let id = new ObjectId(this, savedDocument, partitionKeyValue);
|
|
||||||
let ids = this.documentIds();
|
let ids = this.documentIds();
|
||||||
ids.push(id);
|
ids.push(id);
|
||||||
delete savedDocument._self;
|
delete savedDocument._self;
|
||||||
|
@ -128,7 +132,7 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
.finally(() => this.isExecuting(false));
|
.finally(() => this.isExecuting(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
public onSaveExisitingDocumentClick = (): Promise<any> => {
|
public onSaveExistingDocumentClick = (): Promise<any> => {
|
||||||
const selectedDocumentId = this.selectedDocumentId();
|
const selectedDocumentId = this.selectedDocumentId();
|
||||||
const documentContent = this.selectedDocumentContent();
|
const documentContent = this.selectedDocumentContent();
|
||||||
this.isExecutionError(false);
|
this.isExecutionError(false);
|
||||||
|
@ -151,9 +155,7 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
this._getPartitionKeyDefinition() as PartitionKeyDefinition
|
this._getPartitionKeyDefinition() as PartitionKeyDefinition
|
||||||
);
|
);
|
||||||
|
|
||||||
let partitionKeyValue = partitionKeyArray && partitionKeyArray[0];
|
const id = new ObjectId(this, updatedDocument, partitionKeyArray);
|
||||||
|
|
||||||
const id = new ObjectId(this, updatedDocument, partitionKeyValue);
|
|
||||||
documentId.id(id.id());
|
documentId.id(id.id());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -214,7 +216,7 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
})
|
})
|
||||||
.map((rawDocument: any) => {
|
.map((rawDocument: any) => {
|
||||||
const partitionKeyValue = rawDocument._partitionKeyValue;
|
const partitionKeyValue = rawDocument._partitionKeyValue;
|
||||||
return new DocumentId(this, rawDocument, partitionKeyValue);
|
return new DocumentId(this, rawDocument, [partitionKeyValue]);
|
||||||
});
|
});
|
||||||
|
|
||||||
const merged = currentDocuments.concat(nextDocumentIds);
|
const merged = currentDocuments.concat(nextDocumentIds);
|
||||||
|
@ -303,7 +305,7 @@ export default class MongoDocumentsTab extends DocumentsTab {
|
||||||
// Convert BsonSchema2 to /path format
|
// Convert BsonSchema2 to /path format
|
||||||
partitionKey = {
|
partitionKey = {
|
||||||
kind: partitionKey.kind,
|
kind: partitionKey.kind,
|
||||||
paths: ["/" + this.partitionKeyProperty.replace(/\./g, "/")],
|
paths: ["/" + this.partitionKeyProperties?.[0].replace(/\./g, "/")],
|
||||||
version: partitionKey.version,
|
version: partitionKey.version,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ describe("Collection", () => {
|
||||||
version: 2,
|
version: 2,
|
||||||
});
|
});
|
||||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
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", () => {
|
it("should strip out forward slashes from single partition key paths", () => {
|
||||||
|
@ -47,7 +48,8 @@ describe("Collection", () => {
|
||||||
version: 2,
|
version: 2,
|
||||||
});
|
});
|
||||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
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,
|
version: 2,
|
||||||
});
|
});
|
||||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
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", () => {
|
it("should preserve forward slash on a single partition key", () => {
|
||||||
|
@ -71,7 +74,8 @@ describe("Collection", () => {
|
||||||
version: 2,
|
version: 2,
|
||||||
});
|
});
|
||||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
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", () => {
|
it("should be null if there is no partition key", () => {
|
||||||
|
@ -81,7 +85,7 @@ describe("Collection", () => {
|
||||||
kind: "Hash",
|
kind: "Hash",
|
||||||
});
|
});
|
||||||
collection = generateMockCollectionWithDataModel(collectionsDataModel);
|
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 rid: string;
|
||||||
public databaseId: string;
|
public databaseId: string;
|
||||||
public partitionKey: DataModels.PartitionKey;
|
public partitionKey: DataModels.PartitionKey;
|
||||||
public partitionKeyPropertyHeader: string;
|
public partitionKeyPropertyHeaders: string[];
|
||||||
public partitionKeyProperty: string;
|
public partitionKeyProperties: string[];
|
||||||
public id: ko.Observable<string>;
|
public id: ko.Observable<string>;
|
||||||
public defaultTtl: ko.Observable<number>;
|
public defaultTtl: ko.Observable<number>;
|
||||||
public indexingPolicy: ko.Observable<DataModels.IndexingPolicy>;
|
public indexingPolicy: ko.Observable<DataModels.IndexingPolicy>;
|
||||||
|
@ -120,31 +120,25 @@ export default class Collection implements ViewModels.Collection {
|
||||||
this.requestSchema = data.requestSchema;
|
this.requestSchema = data.requestSchema;
|
||||||
this.geospatialConfig = ko.observable(data.geospatialConfig);
|
this.geospatialConfig = ko.observable(data.geospatialConfig);
|
||||||
|
|
||||||
// TODO fix this to only replace non-excaped single quotes
|
this.partitionKeyPropertyHeaders = this.partitionKey?.paths;
|
||||||
this.partitionKeyProperty =
|
this.partitionKeyProperties = this.partitionKeyPropertyHeaders?.map((partitionKeyPropertyHeader, i) => {
|
||||||
(this.partitionKey &&
|
// TODO fix this to only replace non-excaped single quotes
|
||||||
this.partitionKey.paths &&
|
let partitionKeyProperty = partitionKeyPropertyHeader.replace(/[/]+/g, ".").substring(1).replace(/[']+/g, "");
|
||||||
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;
|
|
||||||
|
|
||||||
if (userContext.apiType === "Mongo" && this.partitionKeyProperty && ~this.partitionKeyProperty.indexOf(`"`)) {
|
if (userContext.apiType === "Mongo" && partitionKeyProperty) {
|
||||||
this.partitionKeyProperty = this.partitionKeyProperty.replace(/["]+/g, "");
|
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
|
return partitionKeyProperty;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.documentIds = ko.observableArray<DocumentId>([]);
|
this.documentIds = ko.observableArray<DocumentId>([]);
|
||||||
this.isCollectionExpanded = ko.observable<boolean>(false);
|
this.isCollectionExpanded = ko.observable<boolean>(false);
|
||||||
|
@ -471,7 +465,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
|
|
||||||
collection: this,
|
collection: this,
|
||||||
masterKey: userContext.masterKey || "",
|
masterKey: userContext.masterKey || "",
|
||||||
collectionPartitionKeyProperty: this.partitionKeyProperty,
|
collectionPartitionKeyProperty: this.partitionKeyProperties?.[0],
|
||||||
collectionId: this.id(),
|
collectionId: this.id(),
|
||||||
databaseId: this.databaseId,
|
databaseId: this.databaseId,
|
||||||
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
||||||
|
@ -710,7 +704,7 @@ export default class Collection implements ViewModels.Collection {
|
||||||
tabPath: "",
|
tabPath: "",
|
||||||
collection: this,
|
collection: this,
|
||||||
masterKey: userContext.masterKey || "",
|
masterKey: userContext.masterKey || "",
|
||||||
collectionPartitionKeyProperty: this.partitionKeyProperty,
|
collectionPartitionKeyProperty: this.partitionKeyProperties?.[0],
|
||||||
collectionId: this.id(),
|
collectionId: this.id(),
|
||||||
databaseId: this.databaseId,
|
databaseId: this.databaseId,
|
||||||
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
isTabsContentExpanded: this.container.isTabsContentExpanded,
|
||||||
|
|
|
@ -150,7 +150,7 @@ export default class ConflictId {
|
||||||
partitionKeyValueResolved
|
partitionKeyValueResolved
|
||||||
);
|
);
|
||||||
|
|
||||||
documentId.partitionKeyProperty = this.partitionKeyProperty;
|
documentId.partitionKeyProperties = [this.partitionKeyProperty];
|
||||||
documentId.partitionKey = this.partitionKey;
|
documentId.partitionKey = this.partitionKey;
|
||||||
|
|
||||||
return documentId;
|
return documentId;
|
||||||
|
|
|
@ -9,21 +9,21 @@ export default class DocumentId {
|
||||||
public self: string;
|
public self: string;
|
||||||
public ts: string;
|
public ts: string;
|
||||||
public id: ko.Observable<string>;
|
public id: ko.Observable<string>;
|
||||||
public partitionKeyProperty: string;
|
public partitionKeyProperties: string[];
|
||||||
public partitionKey: DataModels.PartitionKey;
|
public partitionKey: DataModels.PartitionKey;
|
||||||
public partitionKeyValue: any;
|
public partitionKeyValue: any[];
|
||||||
public stringPartitionKeyValue: string;
|
public stringPartitionKeyValues: string[];
|
||||||
public isDirty: ko.Observable<boolean>;
|
public isDirty: ko.Observable<boolean>;
|
||||||
|
|
||||||
constructor(container: DocumentsTab, data: any, partitionKeyValue: any) {
|
constructor(container: DocumentsTab, data: any, partitionKeyValue: any[]) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.self = data._self;
|
this.self = data._self;
|
||||||
this.rid = data._rid;
|
this.rid = data._rid;
|
||||||
this.ts = data._ts;
|
this.ts = data._ts;
|
||||||
this.partitionKeyValue = partitionKeyValue;
|
this.partitionKeyValue = partitionKeyValue;
|
||||||
this.partitionKeyProperty = container && container.partitionKeyProperty;
|
this.partitionKeyProperties = container?.partitionKeyProperties;
|
||||||
this.partitionKey = container && container.partitionKey;
|
this.partitionKey = container && container.partitionKey;
|
||||||
this.stringPartitionKeyValue = this.getPartitionKeyValueAsString();
|
this.stringPartitionKeyValues = this.getPartitionKeyValueAsString();
|
||||||
this.id = ko.observable(data.id);
|
this.id = ko.observable(data.id);
|
||||||
this.isDirty = ko.observable(false);
|
this.isDirty = ko.observable(false);
|
||||||
}
|
}
|
||||||
|
@ -46,34 +46,35 @@ export default class DocumentId {
|
||||||
}
|
}
|
||||||
|
|
||||||
public partitionKeyHeader(): Object {
|
public partitionKeyHeader(): Object {
|
||||||
if (!this.partitionKeyProperty) {
|
if (!this.partitionKeyProperties || this.partitionKeyProperties.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.partitionKeyValue === undefined) {
|
if (!this.partitionKeyValue || this.partitionKeyValue.length === 0) {
|
||||||
return [{}];
|
return [{}];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [this.partitionKeyValue];
|
return [this.partitionKeyValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPartitionKeyValueAsString(): string {
|
public getPartitionKeyValueAsString(): string[] {
|
||||||
const partitionKeyValue: any = this.partitionKeyValue;
|
return this.partitionKeyValue?.map((partitionKeyValue) => {
|
||||||
const typeOfPartitionKeyValue: string = typeof partitionKeyValue;
|
const typeOfPartitionKeyValue: string = typeof partitionKeyValue;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeOfPartitionKeyValue === "undefined" ||
|
typeOfPartitionKeyValue === "undefined" ||
|
||||||
typeOfPartitionKeyValue === "null" ||
|
typeOfPartitionKeyValue === "null" ||
|
||||||
typeOfPartitionKeyValue === "object"
|
typeOfPartitionKeyValue === "object"
|
||||||
) {
|
) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeOfPartitionKeyValue === "string") {
|
if (typeOfPartitionKeyValue === "string") {
|
||||||
return partitionKeyValue;
|
return partitionKeyValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(partitionKeyValue);
|
return JSON.stringify(partitionKeyValue);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async loadDocument(): Promise<void> {
|
public async loadDocument(): Promise<void> {
|
||||||
|
|
|
@ -22,8 +22,8 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
|
||||||
public rid: string;
|
public rid: string;
|
||||||
public rawDataModel: DataModels.Collection;
|
public rawDataModel: DataModels.Collection;
|
||||||
public partitionKey: DataModels.PartitionKey;
|
public partitionKey: DataModels.PartitionKey;
|
||||||
public partitionKeyProperty: string;
|
public partitionKeyProperties: string[];
|
||||||
public partitionKeyPropertyHeader: string;
|
public partitionKeyPropertyHeaders: string[];
|
||||||
public id: ko.Observable<string>;
|
public id: ko.Observable<string>;
|
||||||
public children: ko.ObservableArray<ViewModels.TreeNode>;
|
public children: ko.ObservableArray<ViewModels.TreeNode>;
|
||||||
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
|
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
|
||||||
|
|
|
@ -3,15 +3,16 @@ import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
|
||||||
export function buildDocumentsQuery(
|
export function buildDocumentsQuery(
|
||||||
filter: string,
|
filter: string,
|
||||||
partitionKeyProperty: string,
|
partitionKeyProperties: string[],
|
||||||
partitionKey: DataModels.PartitionKey
|
partitionKey: DataModels.PartitionKey
|
||||||
): string {
|
): string {
|
||||||
let query = partitionKeyProperty
|
let query =
|
||||||
? `select c.id, c._self, c._rid, c._ts, ${buildDocumentsQueryPartitionProjections(
|
partitionKeyProperties && partitionKeyProperties.length > 0
|
||||||
"c",
|
? `select c.id, c._self, c._rid, c._ts, [${buildDocumentsQueryPartitionProjections(
|
||||||
partitionKey
|
"c",
|
||||||
)} as _partitionKeyValue from c`
|
partitionKey
|
||||||
: `select c.id, c._self, c._rid, c._ts from c`;
|
)}] as _partitionKeyValue from c`
|
||||||
|
: `select c.id, c._self, c._rid, c._ts from c`;
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
query += " " + filter;
|
query += " " + filter;
|
||||||
|
|
Loading…
Reference in New Issue