payload icon indicating copy to clipboard operation
payload copied to clipboard

perf(db-mongodb): use aggregations for relationship querying

Open r1tsuu opened this issue 3 months ago • 1 comments

Uses lookups for relationships querying (where { relationship.name }) of subquerying.

Before, whenever we needed to query by a property from another document, we did this:

const result = await SubModel.find(subQuery, subQueryOptions)

const $in: unknown[] = []

result.forEach((doc) => {
  const stringID = doc._id.toString()
  $in.push(stringID)

  if (mongoose.Types.ObjectId.isValid(stringID)) {
    $in.push(doc._id)
  }
})

Now, we are building an aggregation with lookups to query by those!

Benchmark

Benchmark in test/relationships/int.ts - before https://github.com/r1tsuu/payload/tree/bench/aggregations-before after https://github.com/r1tsuu/payload/tree/bench/aggregations-after

Run with:

pnpm exec cross-env NODE_OPTIONS="--no-deprecation" node 'node_modules/jest/bin/jest.js' '/Users/ritsu/work/payload-3/test/relationships/int.spec.ts' -c '/Users/ritsu/work/payload-3/test/jest.config.js' -t 'Relationships Querying Nested Querying should allow querying several times, one and two level deep'

Code that benchmark uses: https://github.com/r1tsuu/payload/blob/1b8eb31fa56a45316d520e92ddcb2f5c3800a0dd/test/relationships/int.spec.ts#L878-L926

Results:

Before:
image
After:
image

Additionally

  • Ensures we always use the transaction when building the query. We didn't do this before for relationship querying.
  • Unblocks sorting by relationships in mongodb (we support it with postgres/sqlite adapters), can implement in a separate PR.

r1tsuu avatar Oct 24 '24 20:10 r1tsuu