Mam dane w kolekcji mongodb, która wygląda na to:

[
  {
    "_id": 1,
    "type": "big",
    "fields": [11, 12, 13],
    "items": [21, 22, 23]
  },
  {
    "_id": 2,
    "type": "small",
    "fields": [14, 15],
    "items": [24, 25]
  },
  {
    "_id": 3,
    "type": "small",
    "fields": [],
    "items": [41, 42]
  },
  {
    "_id": 4,
    "type": "small",
    "fields": [31, 32, 33],
    "items": []
  }
]

Zajmowałem się zwrotami danych zgodnie z taką procedurą:

Dla każdego dokumentu w kolekcji uzyskaj 1 wartość z jego fields (jeśli są dowolne) i 1 wartość jego items (jeśli są jakieś). Conatenate wszystkie wyniki w jednej tablicy.

Można podsumować to jako wybieranie danych w modzie "Round Robin" z dwóch macierzy utrzymywanych w każdym dokumencie.

Jak osiągnąłbym to w zapytaniu agregacji mongodb? Ta logika nie jest trudna do wdrożenia w kliencie, który łączy się z serwerem Mongo, ale chciałbym pozwolić Mongo zadbać o paginację (z $skip i $limit). Używam MongoDB 4.4.

Powstałe dane wyglądałyby na coś takiego:

[
  {
    "value": 11,
    "type": "field",
    "fromId": 1
  },
  {
    "value": 21,
    "type": "item",
    "fromId": 1
  },
  {
    "value": 14,
    "type": "field",
    "fromId": 2
  },
  {
    "value": 24,
    "type": "item",
    "fromId": 2
  },
  {
    "value": 41,
    "type": "item",
    "fromId": 3
  },
  {
    "value": 31,
    "type": "field",
    "fromId": 4
  },
]
1
shadowtalker 18 marzec 2021, 02:29

1 odpowiedź

Najlepsza odpowiedź

Jeśli rozumiem twoje pytanie; To powinno być rura do pracy. Aby wdrożyć losową funkcjonalność, wystarczy dostosować indeks przekazany do $ arrayrelemat

https://mongoplayground.net/p/ppxv6ftshp.

db.collection.aggregate([
  {$project: {
     types: [
      {type: "field", values: "$fields"},
      {type: "item", values: "$items"}
    ]
  }},
  {$unwind: '$types'},
  {$project: {
    _id: 0,
    value: {$arrayElemAt: ['$types.values', 0]},
    type: '$types.type',
    fromId: '$_id'
  }},
  {$match: {
    value: {$exists: true}
  }}
])

Randomizacja wyglądałaby na coś takiego: https://mongoplayground.net/p/qi1ud53J6YV

db.collection.aggregate([
  {$project: {
     types: [
      {type: "field", values: "$fields"},
      {type: "item", values: "$items"}
    ]
  }},
  {$unwind: '$types'},
  {$project: {
    _id: 0,
    value: {$arrayElemAt: [
      '$types.values',
      {$floor: {$multiply: [{$rand: {}}, {$size: '$types.values'}]}}
    ]},
    type: '$types.type',
    fromId: '$_id'
  }},
  {$match: {
    value: {$exists: true}
  }}
])
1
GitGitBoom 18 marzec 2021, 01:42