@@ -2076,31 +2076,73 @@ export default class Collection extends ShellApiWithMongoClass {
2076
2076
} ) ;
2077
2077
}
2078
2078
2079
- @returnsPromise
2080
- @topologies ( [ Topologies . Sharded ] )
2081
- @apiVersions ( [ ] )
2082
- async getShardDistribution ( ) : Promise < CommandResult > {
2083
- this . _emitCollectionApiCall ( 'getShardDistribution' , { } ) ;
2084
-
2085
- await getConfigDB ( this . _database ) ; // Warns if not connected to mongos
2086
-
2087
- const result = { } as Document ;
2088
- const config = this . _mongo . getDB ( 'config' ) ;
2079
+ /**
2080
+ * Helper for getting collection info for sharded collections.
2081
+ * @throws If the collection is not sharded.
2082
+ * @returns collection info based on given collStats.
2083
+ */
2084
+ async _getShardedCollectionInfo (
2085
+ config : Database ,
2086
+ collStats : Document [ ]
2087
+ ) : Promise < Document > {
2089
2088
const ns = `${ this . _database . _name } .${ this . _name } ` ;
2090
-
2091
- const configCollectionsInfo = await config
2089
+ const existingConfigCollectionsInfo = await config
2092
2090
. getCollection ( 'collections' )
2093
2091
. findOne ( {
2094
2092
_id : ns ,
2095
2093
...onlyShardedCollectionsInConfigFilter ,
2096
2094
} ) ;
2097
- if ( ! configCollectionsInfo ) {
2095
+
2096
+ if ( existingConfigCollectionsInfo !== null ) {
2097
+ return existingConfigCollectionsInfo ;
2098
+ }
2099
+
2100
+ // If the collection info is not found, check if it is timeseries and use the bucket
2101
+ const timeseriesShardStats = collStats . find (
2102
+ ( extractedShardStats ) =>
2103
+ typeof extractedShardStats . storageStats . timeseries !== 'undefined'
2104
+ ) ;
2105
+
2106
+ if ( ! timeseriesShardStats ) {
2098
2107
throw new MongoshInvalidInputError (
2099
2108
`Collection ${ this . _name } is not sharded` ,
2100
2109
ShellApiErrors . NotConnectedToShardedCluster
2101
2110
) ;
2102
2111
}
2103
2112
2113
+ const { storageStats } = timeseriesShardStats ;
2114
+
2115
+ const timeseries : Document = storageStats . timeseries ;
2116
+ const timeseriesBucketNs : string = timeseries . bucketsNs ;
2117
+
2118
+ const timeseriesCollectionInfo = await config
2119
+ . getCollection ( 'collections' )
2120
+ . findOne ( {
2121
+ _id : timeseriesBucketNs ,
2122
+ ...onlyShardedCollectionsInConfigFilter ,
2123
+ } ) ;
2124
+
2125
+ if ( ! timeseriesCollectionInfo ) {
2126
+ throw new MongoshRuntimeError (
2127
+ `Error finding collection information for ${ timeseriesBucketNs } ` ,
2128
+ CommonErrors . CommandFailed
2129
+ ) ;
2130
+ }
2131
+
2132
+ return timeseriesCollectionInfo ;
2133
+ }
2134
+
2135
+ @returnsPromise
2136
+ @topologies ( [ Topologies . Sharded ] )
2137
+ @apiVersions ( [ ] )
2138
+ async getShardDistribution ( ) : Promise < CommandResult > {
2139
+ this . _emitCollectionApiCall ( 'getShardDistribution' , { } ) ;
2140
+
2141
+ await getConfigDB ( this . _database ) ; // Warns if not connected to mongos
2142
+
2143
+ const result = { } as Document ;
2144
+ const config = this . _mongo . getDB ( 'config' ) ;
2145
+
2104
2146
const collStats = await (
2105
2147
await this . aggregate ( { $collStats : { storageStats : { } } } )
2106
2148
) . toArray ( ) ;
@@ -2115,12 +2157,15 @@ export default class Collection extends ShellApiWithMongoClass {
2115
2157
avgObjSize : number ;
2116
2158
} [ ] = [ ] ;
2117
2159
2160
+ const configCollectionsInfo = await this . _getShardedCollectionInfo (
2161
+ config ,
2162
+ collStats
2163
+ ) ;
2164
+
2118
2165
await Promise . all (
2119
- collStats . map ( ( extShardStats ) =>
2166
+ collStats . map ( ( extractedShardStats ) =>
2120
2167
( async ( ) : Promise < void > => {
2121
- // Extract and store only the relevant subset of the stats for this shard
2122
- const { shard } = extShardStats ;
2123
-
2168
+ const { shard } = extractedShardStats ;
2124
2169
// If we have an UUID, use that for lookups. If we have only the ns,
2125
2170
// use that. (On 5.0+ servers, config.chunk has uses the UUID, before
2126
2171
// that it had the ns).
@@ -2131,39 +2176,43 @@ export default class Collection extends ShellApiWithMongoClass {
2131
2176
const [ host , numChunks ] = await Promise . all ( [
2132
2177
config
2133
2178
. getCollection ( 'shards' )
2134
- . findOne ( { _id : extShardStats . shard } ) ,
2179
+ . findOne ( { _id : extractedShardStats . shard } ) ,
2135
2180
config . getCollection ( 'chunks' ) . countDocuments ( countChunksQuery ) ,
2136
2181
] ) ;
2137
2182
const shardStats = {
2138
2183
shardId : shard ,
2139
2184
host : host !== null ? host . host : null ,
2140
- size : extShardStats . storageStats . size ,
2141
- count : extShardStats . storageStats . count ,
2185
+ size : extractedShardStats . storageStats . size ,
2186
+ count : extractedShardStats . storageStats . count ,
2142
2187
numChunks : numChunks ,
2143
- avgObjSize : extShardStats . storageStats . avgObjSize ,
2188
+ avgObjSize : extractedShardStats . storageStats . avgObjSize ,
2144
2189
} ;
2145
2190
2146
2191
const key = `Shard ${ shardStats . shardId } at ${ shardStats . host } ` ;
2147
2192
2148
- const estChunkData =
2193
+ // In sharded timeseries collections we do not have a count
2194
+ // so we intentionally pass NaN as a result to the client.
2195
+ const shardStatsCount : number = shardStats . count ?? NaN ;
2196
+
2197
+ const estimatedChunkDataPerChunk =
2149
2198
shardStats . numChunks === 0
2150
2199
? 0
2151
2200
: shardStats . size / shardStats . numChunks ;
2152
- const estChunkCount =
2201
+ const estimatedDocsPerChunk =
2153
2202
shardStats . numChunks === 0
2154
2203
? 0
2155
- : Math . floor ( shardStats . count / shardStats . numChunks ) ;
2204
+ : Math . floor ( shardStatsCount / shardStats . numChunks ) ;
2156
2205
2157
2206
result [ key ] = {
2158
2207
data : dataFormat ( coerceToJSNumber ( shardStats . size ) ) ,
2159
- docs : shardStats . count ,
2208
+ docs : shardStatsCount ,
2160
2209
chunks : shardStats . numChunks ,
2161
- 'estimated data per chunk' : dataFormat ( estChunkData ) ,
2162
- 'estimated docs per chunk' : estChunkCount ,
2210
+ 'estimated data per chunk' : dataFormat ( estimatedChunkDataPerChunk ) ,
2211
+ 'estimated docs per chunk' : estimatedDocsPerChunk ,
2163
2212
} ;
2164
2213
2165
2214
totals . size += coerceToJSNumber ( shardStats . size ) ;
2166
- totals . count += coerceToJSNumber ( shardStats . count ) ;
2215
+ totals . count += coerceToJSNumber ( shardStatsCount ) ;
2167
2216
totals . numChunks += coerceToJSNumber ( shardStats . numChunks ) ;
2168
2217
2169
2218
conciseShardsStats . push ( shardStats ) ;
@@ -2326,7 +2375,7 @@ export default class Collection extends ShellApiWithMongoClass {
2326
2375
return await this . _mongo . _serviceProvider . getSearchIndexes (
2327
2376
this . _database . _name ,
2328
2377
this . _name ,
2329
- indexName as string | undefined ,
2378
+ indexName ,
2330
2379
{ ...( await this . _database . _baseOptions ( ) ) , ...options }
2331
2380
) ;
2332
2381
}
@@ -2355,7 +2404,7 @@ export default class Collection extends ShellApiWithMongoClass {
2355
2404
this . _name ,
2356
2405
[
2357
2406
{
2358
- name : ( indexName as string | undefined ) ?? 'default' ,
2407
+ name : indexName ?? 'default' ,
2359
2408
// Omitting type when it is 'search' for compat with older servers
2360
2409
...( type &&
2361
2410
type !== 'search' && { type : type as 'search' | 'vectorSearch' } ) ,
0 commit comments