@pnp/cli-microsoft365 7.5.0-beta.940b241 → 7.5.0-beta.c0c1edf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,16 +38,15 @@ class SpoSearchCommand extends SpoCommand {
38
38
  if (this.verbose) {
39
39
  await logger.logToStderr(`Executing search query '${args.options.queryText}' on site at ${webUrl}...`);
40
40
  }
41
- const startRow = args.options.startRow ? args.options.startRow : 0;
42
- const results = await this.executeSearchQuery(logger, args, webUrl, [], startRow);
41
+ const results = await this.executeSearchQuery(logger, args, webUrl, []);
43
42
  this.printResults(logger, args, results);
44
43
  }
45
44
  catch (err) {
46
45
  this.handleRejectedODataJsonPromise(err);
47
46
  }
48
47
  }
49
- async executeSearchQuery(logger, args, webUrl, resultSet, startRow) {
50
- const requestUrl = await this.getRequestUrl(webUrl, logger, args, startRow);
48
+ async executeSearchQuery(logger, args, webUrl, resultSet, lastDocId = '0') {
49
+ const requestUrl = await this.getRequestUrl(webUrl, logger, args, lastDocId);
51
50
  const requestOptions = {
52
51
  url: requestUrl,
53
52
  headers: {
@@ -57,26 +56,36 @@ class SpoSearchCommand extends SpoCommand {
57
56
  };
58
57
  const searchResult = await request.get(requestOptions);
59
58
  resultSet.push(searchResult);
60
- if (args.options.allResults && startRow + searchResult.PrimaryQueryResult.RelevantResults.RowCount < searchResult.PrimaryQueryResult.RelevantResults.TotalRows) {
61
- const nextStartRow = startRow + searchResult.PrimaryQueryResult.RelevantResults.RowCount;
62
- return this.executeSearchQuery(logger, args, webUrl, resultSet, nextStartRow);
59
+ const rowLimit = args.options.rowLimit ? args.options.rowLimit : 500;
60
+ if (args.options.allResults && searchResult.PrimaryQueryResult.RelevantResults.RowCount === rowLimit) {
61
+ if (this.verbose) {
62
+ await logger.logToStderr(`Processing search query, retrieved ${resultSet.length * searchResult.PrimaryQueryResult.RelevantResults.RowCount} of ${resultSet[0].PrimaryQueryResult.RelevantResults.TotalRows} items...`);
63
+ }
64
+ // When running in allResults mode, paging is done using the DocId property
65
+ // This is a more stable way than using the StartRow property.
66
+ // Explanation: https://learn.microsoft.com/sharepoint/dev/general-development/pagination-for-large-result-sets
67
+ const lastRow = searchResult.PrimaryQueryResult.RelevantResults.Table.Rows[searchResult.PrimaryQueryResult.RelevantResults.RowCount - 1];
68
+ const newLastDocId = lastRow.Cells.filter(cell => cell.Key === 'DocId')[0].Value;
69
+ return this.executeSearchQuery(logger, args, webUrl, resultSet, newLastDocId);
63
70
  }
64
71
  return resultSet;
65
72
  }
66
- async getRequestUrl(webUrl, logger, args, startRow) {
73
+ async getRequestUrl(webUrl, logger, args, lastDocId) {
67
74
  // get the list of selected properties
68
75
  const selectPropertiesArray = this.getSelectPropertiesArray(args);
76
+ // get the sort list
77
+ const sortList = this.getSortList(args);
69
78
  // transform arg data to query string parameters
70
- const propertySelectRequestString = `&selectproperties='${formatting.encodeQueryParameter(selectPropertiesArray.join(","))}'`;
71
- const startRowRequestString = `&startrow=${startRow ? startRow : 0}`;
72
- const rowLimitRequestString = args.options.rowLimit ? `&rowlimit=${args.options.rowLimit}` : ``;
79
+ const propertySelectRequestString = `&selectproperties='${formatting.encodeQueryParameter(selectPropertiesArray.join(','))}'`;
80
+ const startRowRequestString = `&startrow=${args.options.startRow ? args.options.startRow : 0}`;
81
+ const rowLimitRequestString = args.options.rowLimit ? `&rowlimit=${args.options.rowLimit}` : (args.options.allResults ? `&rowlimit=500` : '');
73
82
  const sourceIdRequestString = args.options.sourceId ? `&sourceid='${args.options.sourceId}'` : ``;
74
- const trimDuplicatesRequestString = `&trimduplicates=${args.options.trimDuplicates ? args.options.trimDuplicates : "false"}`;
75
- const enableStemmingRequestString = `&enablestemming=${typeof (args.options.enableStemming) === 'undefined' ? "true" : args.options.enableStemming}`;
83
+ const trimDuplicatesRequestString = `&trimduplicates=${args.options.trimDuplicates ? args.options.trimDuplicates : 'false'}`;
84
+ const enableStemmingRequestString = `&enablestemming=${typeof (args.options.enableStemming) === 'undefined' ? 'true' : args.options.enableStemming}`;
76
85
  const cultureRequestString = args.options.culture ? `&culture=${args.options.culture}` : ``;
77
86
  const refinementFiltersRequestString = args.options.refinementFilters ? `&refinementfilters='${args.options.refinementFilters}'` : ``;
78
87
  const queryTemplateRequestString = args.options.queryTemplate ? `&querytemplate='${args.options.queryTemplate}'` : ``;
79
- const sortListRequestString = args.options.sortList ? `&sortList='${formatting.encodeQueryParameter(args.options.sortList)}'` : ``;
88
+ const sortListRequestString = sortList ? `&sortList='${sortList}'` : ``;
80
89
  const rankingModelIdRequestString = args.options.rankingModelId ? `&rankingmodelid='${args.options.rankingModelId}'` : ``;
81
90
  const propertiesRequestString = this.getPropertiesRequestString(args);
82
91
  const refinersRequestString = args.options.refiners ? `&refiners='${args.options.refiners}'` : ``;
@@ -86,8 +95,9 @@ class SpoSearchCommand extends SpoCommand {
86
95
  const processBestBetsRequestString = typeof (args.options.processBestBets) === 'undefined' ? `` : `&processbestbets=${args.options.processBestBets}`;
87
96
  const enableQueryRulesRequestString = typeof (args.options.enableQueryRules) === 'undefined' ? `` : `&enablequeryrules=${args.options.enableQueryRules}`;
88
97
  const processPersonalFavoritesRequestString = typeof (args.options.processPersonalFavorites) === 'undefined' ? `` : `&processpersonalfavorites=${args.options.processPersonalFavorites}`;
98
+ const indexDocIdQueryText = args.options.allResults ? ` IndexDocId>${lastDocId}` : '';
89
99
  // construct single requestUrl
90
- const requestUrl = `${webUrl}/_api/search/query?querytext='${args.options.queryText}'`.concat(propertySelectRequestString, startRowRequestString, rowLimitRequestString, sourceIdRequestString, trimDuplicatesRequestString, enableStemmingRequestString, cultureRequestString, refinementFiltersRequestString, queryTemplateRequestString, sortListRequestString, rankingModelIdRequestString, propertiesRequestString, refinersRequestString, hiddenConstraintsRequestString, clientTypeRequestString, enablePhoneticRequestString, processBestBetsRequestString, enableQueryRulesRequestString, processPersonalFavoritesRequestString);
100
+ const requestUrl = `${webUrl}/_api/search/query?querytext='${args.options.queryText}${indexDocIdQueryText}'`.concat(propertySelectRequestString, startRowRequestString, rowLimitRequestString, sourceIdRequestString, trimDuplicatesRequestString, enableStemmingRequestString, cultureRequestString, refinementFiltersRequestString, queryTemplateRequestString, sortListRequestString, rankingModelIdRequestString, propertiesRequestString, refinersRequestString, hiddenConstraintsRequestString, clientTypeRequestString, enablePhoneticRequestString, processBestBetsRequestString, enableQueryRulesRequestString, processPersonalFavoritesRequestString);
91
101
  if (this.debug) {
92
102
  await logger.logToStderr(`RequestURL: ${requestUrl}`);
93
103
  }
@@ -96,7 +106,7 @@ class SpoSearchCommand extends SpoCommand {
96
106
  getPropertiesRequestString(args) {
97
107
  let properties = args.options.properties ? args.options.properties : '';
98
108
  if (args.options.sourceName) {
99
- if (properties && !properties.endsWith(",")) {
109
+ if (properties && !properties.endsWith(',')) {
100
110
  properties += `,`;
101
111
  }
102
112
  properties += `SourceName:${args.options.sourceName},SourceLevel:SPSite`;
@@ -104,9 +114,26 @@ class SpoSearchCommand extends SpoCommand {
104
114
  return properties ? `&properties='${properties}'` : ``;
105
115
  }
106
116
  getSelectPropertiesArray(args) {
107
- return args.options.selectProperties
108
- ? args.options.selectProperties.split(",")
109
- : ["Title", "OriginalPath"];
117
+ const selectProperties = args.options.selectProperties
118
+ ? args.options.selectProperties.split(',')
119
+ : ['Title', 'OriginalPath'];
120
+ if (args.options.allResults) {
121
+ selectProperties.filter(p => p.toLowerCase() !== 'docid').push('DocId');
122
+ }
123
+ return selectProperties;
124
+ }
125
+ getSortList(args) {
126
+ const sortList = [];
127
+ if (args.options.allResults) {
128
+ sortList.push(formatting.encodeQueryParameter('[DocId]:ascending'));
129
+ }
130
+ if (args.options.sortList) {
131
+ const sortListArray = args.options.sortList.split(',');
132
+ sortListArray.forEach(sortItem => {
133
+ sortList.push(formatting.encodeQueryParameter(sortItem));
134
+ });
135
+ }
136
+ return sortList.join(',');
110
137
  }
111
138
  async printResults(logger, args, results) {
112
139
  if (args.options.rawOutput) {
@@ -116,9 +143,9 @@ class SpoSearchCommand extends SpoCommand {
116
143
  await logger.log(this.getParsedOutput(args, results));
117
144
  }
118
145
  if (!args.options.output || cli.shouldTrimOutput(args.options.output)) {
119
- await logger.log("# Rows: " + results[results.length - 1].PrimaryQueryResult.RelevantResults.TotalRows);
120
- await logger.log("# Rows (Including duplicates): " + results[results.length - 1].PrimaryQueryResult.RelevantResults.TotalRowsIncludingDuplicates);
121
- await logger.log("Elapsed Time: " + this.getElapsedTime(results));
146
+ await logger.log('# Rows: ' + results[results.length - 1].PrimaryQueryResult.RelevantResults.TotalRows);
147
+ await logger.log('# Rows (Including duplicates): ' + results[results.length - 1].PrimaryQueryResult.RelevantResults.TotalRowsIncludingDuplicates);
148
+ await logger.log('Elapsed Time: ' + this.getElapsedTime(results));
122
149
  }
123
150
  }
124
151
  getElapsedTime(results) {
@@ -245,6 +272,9 @@ _SpoSearchCommand_instances = new WeakSet(), _SpoSearchCommand_initTelemetry = f
245
272
  if (args.options.startRow && !isNumber(args.options.startRow)) {
246
273
  return `${args.options.startRow} is not a valid number`;
247
274
  }
275
+ if (args.options.startRow && args.options.allResults) {
276
+ return 'You cannot specify startRow when allResults is set';
277
+ }
248
278
  if (args.options.culture && !isNumber(args.options.culture)) {
249
279
  return `${args.options.culture} is not a valid number`;
250
280
  }
@@ -25,7 +25,7 @@ m365 spo search [options]
25
25
  : The web against which we want to execute the query. If the parameter is not defined, the query is executed against the web that's used when logging in to the SPO environment.
26
26
 
27
27
  `--allResults`
28
- : Set, to get all results of the search query, instead of the number specified by the `rowlimit` (default: 10)
28
+ : Set, to get all results of the search query in batches of 500.
29
29
 
30
30
  `--rowLimit [rowLimit]`
31
31
  : The number of rows to be returned. When the `allResults` option is used, the specified value will define the size of retrieved batches
@@ -55,7 +55,7 @@ m365 spo search [options]
55
55
  : The ID of the ranking model to use for the query.
56
56
 
57
57
  `--startRow [startRow]`
58
- : The first row that is included in the search results that are returned. You use this parameter when you want to implement paging for search results.
58
+ : The first row that is included in the search results that are returned. You use this parameter when you want to implement manual paging for search results.
59
59
 
60
60
  `--properties [properties]`
61
61
  : Additional properties for the query.
@@ -90,6 +90,10 @@ m365 spo search [options]
90
90
 
91
91
  <Global />
92
92
 
93
+ ## Remarks
94
+
95
+ When using the `--allResults` option, you cannot use the `--startRow` option. Only use `--startRow` for manual paging purposes.
96
+
93
97
  ## Examples
94
98
 
95
99
  Execute search query to retrieve all Document Sets (ContentTypeId = _0x0120D520_) for the English locale
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnp/cli-microsoft365",
3
- "version": "7.5.0-beta.940b241",
3
+ "version": "7.5.0-beta.c0c1edf",
4
4
  "description": "Manage Microsoft 365 and SharePoint Framework projects on any platform",
5
5
  "license": "MIT",
6
6
  "main": "./dist/api.js",