buildMongoPipeline.ts 1.9 KB
Newer Older
1
import { DocumentSelection } from '../types'
aleclofabbro's avatar
aleclofabbro committed
2
3
import { isUnionLookupField } from '../buildDocumentSelection'
export const buildMongoPipeline = (docS: DocumentSelection, notTop?: boolean) => {
4
5
6
7
  const lookups = [] as any[]
  const project = {} as Record<string, string>

  Object.entries(docS).forEach(([alias, field]) => {
aleclofabbro's avatar
aleclofabbro committed
8
9
10
11
    if (isUnionLookupField(field)) {
      const $mainMatchUnionMatch = { $or: [] as any[] }
      const $mainMatch = { $and: [$mainMatchUnionMatch] }
      const pipeline = [{ $match: $mainMatch }] as any[]
12
      const $lookup = {
aleclofabbro's avatar
aleclofabbro committed
13
14
        as: field.alias,
        let: {} as Record<string, string>,
15
        from: 'Graph',
aleclofabbro's avatar
aleclofabbro committed
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        pipeline,
      }

      if (field.traverseRelation) {
        if (field.traverseRelation === '_rel') {
          $lookup.let.nodeId = '$_id'

          notTop &&
            $mainMatch.$and.push({
              // $expr: { $eq: [`$${field.traverseRelation}`, '$$nodeId'] },
              $expr: { $eq: [`$_subj`, '$$nodeId'] },
            } as any)
        } else {
          $lookup.let.edgeSide = `$${field.traverseRelation}` //=== '_obj' ? '$_subj' : '$_obj'
          notTop && $mainMatch.$and.push({ $expr: { $eq: [`$_id`, '$$edgeSide'] } } as any)
        }
32
      }
aleclofabbro's avatar
aleclofabbro committed
33

34
      field.lookups.forEach((fieldLookup) => {
aleclofabbro's avatar
aleclofabbro committed
35
36
        const $match = { $and: [{ __typename: fieldLookup.__typename }] as any[] }
        $mainMatchUnionMatch.$or.push($match)
37
        fieldLookup.match && $match.$and.push(fieldLookup.match)
aleclofabbro's avatar
aleclofabbro committed
38
        pipeline.push(...buildMongoPipeline(fieldLookup.select, true))
39
      })
aleclofabbro's avatar
aleclofabbro committed
40
      project[field.alias] = `$${field.alias}`
41
42
43
      lookups.push({
        $lookup,
      })
aleclofabbro's avatar
aleclofabbro committed
44
45
    } else {
      project[alias] = `$${field.fieldName}`
46
47
    }
  })
aleclofabbro's avatar
aleclofabbro committed
48
49
50
51
52
53
54
55
56
  if (notTop) {
    const stages = [...lookups]
    if (Object.keys(project).length) {
      stages.push({ $project: project })
    }
    return stages
  } else {
    const stages = lookups[0].$lookup.pipeline
    return stages
57
58
  }
}