"Low-level" MongoDB

czyli kolekcja to nie tylko find

Co może kolekcja?

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

Tego nie wkrótce nie będzie...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To już znamy...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To da się zastąpić...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To dotyczy indeksów...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To dotyczy indeksów...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

KOLEJNA PREZENTACJA!?

To dotyczy utrzymania...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To dotyczy utrzymania...

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

KOLEJNA PREZENTACJA!?

To co nam zostało?

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

To co nam zostało?

aggregate, bulkWrite, copyTo, count, createIndex, dataSize, deleteOne, deleteMany, distinct, drop, dropIndex, dropIndexes, ensureIndex, explain, find, findAndModify, findOne, findOneAndDelete, findOneAndReplace, findOneAndUpdate, getIndexes, getShardDistribution, getShardVersion, group, insert, insertOne, insertMany, isCapped, latencyStats, mapReduce, reIndex, remove, renameCollection, replaceOne, save, stats, storageSize, totalIndexSize, totalSize, update, updateOne, updateMany, validate

.distinct()

Zwraca wszystkie wartości danego pola (null oznacza brak).
// Definition
db.collection.distinct(field, query, options)

// Meteor
const emails = await Users.rawCollection().distinct('email');
// [ 'john@doe.com',
//   'test@example.com',
//   ...
// ]

.distinct()

Zwraca wszystkie wartości danego pola (null oznacza brak).
// Definition
db.collection.distinct(field, query, options)

// Meteor
const emails = await Users.rawCollection().distinct('email');
// [ 'john@doe.com',
//   'test@example.com',
//   ...
// ]

.bulkWrite()

Wykonuje ciąg operacji modyfikujących kolekcję.
// Definition
db.collection.bulkWrite(operations, {ordered, writeConcern})

// Meteor
await Users.rawCollection().bulkWrite([
  // Insert
  {insertOne: {document: doc}},
  
  // Update
  {updateOne:  {filter: query, update: modifier, upsert: bool}},
  {updateMany: {filter: query, update: modifier, upsert: bool}},

  // Delete
  {deleteOne:  {filter: query}},
  {deleteMany: {filter: query}},

  // Replace
  {replaceOne: {filter: query, replacement: doc, upsert: bool}}
]);

.bulkWrite()

Wykonuje ciąg operacji modyfikujących kolekcję.
// Definition
db.collection.bulkWrite(operations, {ordered, writeConcern})

// Meteor
await Users.rawCollection().bulkWrite([
  // Insert
  {insertOne: {document: doc}},
  
  // Update
  {updateOne:  {filter: query, update: modifier, upsert: bool}},
  {updateMany: {filter: query, update: modifier, upsert: bool}},

  // Delete
  {deleteOne:  {filter: query}},
  {deleteMany: {filter: query}},

  // Replace
  {replaceOne: {filter: query, replacement: doc, upsert: bool}}
]);

.aggregate()

// Definition
db.collection.aggregate(pipeline, options)

// Meteor
await Users.rawCollection().aggregate(pipeline).toArray();

.aggregate()

// Definition
db.collection.aggregate(pipeline, options)

// Meteor
await Users.rawCollection().aggregate(pipeline).toArray();

.aggregate()

const pipeline = [
  {$addFields: ...},
  {$bucket: ...},
  {$bucketAuto: ...},
  {$collStats: ...},
  {$count: ...},
  {$facet: ...},
  {$geoNear: ...},
  {$graphLookup: ...},
  {$group: ...},
  {$indexStats: ...},
  {$limit: ...},
  {$lookup: ...},
  {$match: ...},
  {$out: ...},
  {$project: ...},
  {$redact: ...},
  {$replaceRoot: ...},
  {$sample: ...},
  {$skip: ...},
  {$sort: ...},
  {$sortByCount: ...},
  {$unwind: ...}
];

.mapReduce()

.mapReduce()

.aggregate(), lecz zamiast operatorów sami piszemy funkcje

Po co?

.aggregate()

const pipeline = [
  {$match: {
    customerId: {$exists: true},
    firstName:  {$nin: ['Walk', 'WALK', 'Walkin']}
  }},

  {$project: {
    company:     {$ifNull: ['$company', '']},
    countryCode: '$countryCode',
    customerId:  '$customerId',
    email:       '$email',
    firstName:   '$firstName',
    lastName:    '$lastName',
    phoneNumber: '$phoneNumber'
  }},

  {$lookup: {
    from: Customer._name,
    localField: 'customerId',
    foreignField: '_id',
    as: 'customer'
  }},

  {$match: {customer: {$ne: []}}},

  {$unwind: '$customer'},

  {$project: {
    company:     '$company',
    countryCode: '$countryCode',
    customer:    '$customer',
    email:       '$email',
    firstName:   '$firstName',
    lastName:    '$lastName',
    phoneNumber: '$phoneNumber',

    _company: {$and: [
      {$ne: ['$company', '']},
      {$ne: ['$company', '$customer.company']}
    ]},

    _countryCode: {$ne: ['$countryCode', '$customer.countryCode']},
    _email:       {$ne: ['$email',       '$customer.primaryEmail']},
    _firstName:   {$ne: ['$firstName',   '$customer.firstName']},
    _lastName:    {$ne: ['$lastName',    '$customer.lastName']},
    _phoneNumber: {$ne: ['$phoneNumber', '$customer.phoneNumber']}
  }},

  {$match: {$or: [
    {_company:     true},
    {_countryCode: true},
    {_email:       true},
    {_firstName:   true},
    {_lastName:    true},
    {_phoneNumber: true}
  ]}}
];

.aggregate() + .bulkWrite()

const diffs = Reservations.rawCollection().aggregate([
  {$match: {
    restaurantId,
    company: {$exists: true, $ne: ''},
    organisationId: {$exists: false}
  }},
  {$project: {_id: '$_id', company: '$company', customerId: '$customerId'}},
  {$lookup: {
    from: '__Organisations',
    localField: 'customerId',
    foreignField: 'ownerId',
    as: 'organisations'
  }},
  {$unwind: '$organisations'},
  {$project: {_id: '$_id', organisationId: '$organisations._id', omit: {$or: [
    {$eq: ['$organisations.isDefault', true]},
    {$ne: ['$company', '$organisations.name']}
  ]}}},
  {$match: {omit: false}},
  {$project: {_id: '$_id', organisationId: '$organisationId'}}
]).toArray().await().map(diff => ({
  updateOne: {
    filter: {_id: diff._id},
    update: {$set: {organisationId: diff.organisationId}}
  }
}));

if (diffs.length)
  await Reservations.rawCollection().bulkWrite(diffs);