Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-95065

Replace listCollections with equivalent aggregation

    • Type: Icon: Improvement Improvement
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Catalog and Routing

      The following aggregation provides the same output for listCollections:

      [{
              $listCatalog: {}
          },
          // Replace this with the actual database used.
          {
              $match: {
                  db: "test"
              }
          },
          {
              $replaceWith: {
                  $switch: {
                      branches: [{
                              case: {
                                  $eq: [
                                      "$type",
                                      "view"
                                  ]
                              },
                              then: {
                                  name: "$name",
                                  type: "$type",
                                  timeseriesKey: "$name",
                                  options: {
                                      viewOn: "$viewOn",
                                      pipeline: "$pipeline",
                                      collation: "$collation"
                                  },
                                  info: {
                                      readOnly: true
                                  }
                              }
                          },
                          {
                              case: {
                                  $eq: [
                                      "$type",
                                      "timeseries"
                                  ]
                              },
                              then: {
                                  name: "$name",
                                  type: "$type",
                                  timeseriesKey: "$viewOn"
                              }
                          },
                          {
                              case: {
                                  $eq: [
                                      "$type",
                                      "collection"
                                  ]
                              },
                              then: {
                                  name: "$name",
                                  timeseriesKey: "$name",
                                  type: "$type",
                                  info: {
                                      uuid: "$md.options.uuid"
                                  },
                                  idIndex: {
                                      $getField: {
                                          field: "spec",
                                          input: {
                                              $arrayElemAt: [{
                                                      $filter: {
                                                          input: "$md.indexes",
                                                          cond: {
                                                              $eq: [
                                                                  "$$this.spec.name",
                                                                  "_id_"
                                                              ]
                                                          }
                                                      }
                                                  },
                                                  0
                                              ]
                                          }
                                      }
                                  },
                                  options: {
                                      $unsetField: {
                                          field: "uuid",
                                          input: "$md.options"
                                      }
                                  }
                              }
                          }
                      ],
                      default: {}
                  }
              }
          },
          {
              $group: {
                  _id: "$timeseriesKey",
                  entries: {
                      "$addToSet": "$$ROOT"
                  }
              }
          },
          {
              $project: {
                  entries: {
                      "$map": {
                          "input": "$entries",
                          "in": {
                              // Special handling for timeseries, this will replace the "options" with the
                              // ones obtained in the associated buckets collection.
                              "$cond": {
                                  "if": {
                                      $eq: [
                                          "$$this.type",
                                          "timeseries"
                                      ]
                                  },
                                  "then": {
                                      "$setField": {
                                          "field": "options",
                                          "input": "$$this",
                                          "value": {
                                              $let: {
                                                  vars: {
                                                      tsOptions: {
                                                          $getField: {
                                                              field: "options",
                                                              input: {
                                                                  $arrayElemAt: [{
                                                                          $filter: {
                                                                              input: "$entries",
                                                                              as: "entry",
                                                                              cond: {
                                                                                  $eq: [
                                                                                      "$$entry.name",
                                                                                      "$$this.timeseriesKey"
                                                                                  ]
                                                                              }
                                                                          }
                                                                      },
                                                                      0
                                                                  ]
                                                              }
                                                          }
                                                      }
                                                  },
                                                  in: {
                                                      // Replace these projections with the allowed fields present in
                                                      // kAllowedCollectionCreationOptions
                                                      storageEngine: "$$tsOptions.storageEngine",
                                                      indexOptionDefaults: "$$tsOptions.indexOptionDefaults",
                                                      collation: "$$tsOptions.collation",
                                                      timeseries: "$$tsOptions.timeseries",
                                                      expireAfterSeconds: "$$tsOptions.expireAfterSeconds",
                                                      temp: "$$tsOptions.temp"
                                                  }
                                              }
                                          }
                                      }
                                  },
                                  "else": "$$this"
                              }
                          }
                      }
                  }
              }
          },
          {
              $unwind: "$entries"
          },
          {
              "$replaceWith": "$entries"
          },
          {
              $unset: "timeseriesKey"
          },
          // Replace "false" with the actual value obtained at runtime from opCtx->readOnly()
          {
              $set: {
                  info: {
                      readOnly: {
                          $ifNull: [
                              "$info.readOnly",
                              false
                          ]
                      }
                  }
              }
          }
      ]
      

      Note that the aggregation does assume some invariants such as:

      • The element looked for in the arrays always exist

            Assignee:
            Unassigned Unassigned
            Reporter:
            jordi.olivares-provencio@mongodb.com Jordi Olivares Provencio
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: