Categories
MongoDB Node.js Basics

Node.js Basics — MongoDB Collations

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Collations

Collations are sets of sorting rules that are used when we do string order for specific languages and locales.

We can specify the collation property when we create the collection.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test", {
      collation: { locale: "en" },
    });
    const testCollection = await db.collection('test');
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const query = {};
    const projection = { name: 1 };
    const cursor = testCollection
      .find(query)
      .project(projection);
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We call createCollection with the collection name as the first argument.

The 2nd argument is an object where we have the collation property to set the collation rule.

Then we call find to query the collection.

Assign a Collation to an Index

We can also assign a collection to an index.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const query = { name: 'apple' };
    const options = { "collation": { "locale": "en_US" } };
    const cursor = testCollection
      .find(query, options)
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We have:

await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });

We called createIndex with the fields to index in the first argument.

The 2nd argument has the collation options.

Then we can use it by writing:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = testCollection
      .find()
      .sort({ "name": -1 });
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We sort the name field with the sort method in descending order.

Conclusion

We can add collations applying sorting rules for a specific language with MongoDB.

Categories
MongoDB Node.js Basics

Node.js Basics — MongoDB Collation Rules for Deletion and Aggregation

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Collation and findOneAndDelete

We can set collation rules with the findOneAndDelete method.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    testCollection
      .findOneAndDelete(
        { qty: { $gt: "5" } },
        { collation: { locale: "en", numericOrdering: true } },
      );
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We call findOneAndDelete with an object with the collation property to set the locale for the collation rule.

Collation and Aggregation

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "apples", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = await testCollection
      .aggregate(
        [
          { $group: { "_id": "$name", "nameCount": { "$sum": 1 } } },
          { $sort: { "_id": 1 } },
        ],
        { collation: { locale: "en", numericOrdering: true } },
      );
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We call aggregate on testCollection with an array of aggregation rules that we want to apply.

We aggregate the names together and get the count of each name.

Then we sort by the _id value which is the value of the name field.

We then sort by the _id in ascending order.

In the 2nd argument, we set the collation rule.

Then the result we get from the cursor is:

{ _id: 'apples', nameCount: 2 }
{ _id: 'avocados', nameCount: 1 }
{ _id: 'oranges', nameCount: 1 }

Conclusion

We can use collation rules with the findOneAndDelete and aggregate methods of a MongoDB collection object.

Categories
MongoDB Node.js Basics

Node.js Basics — MongoDB Collation and Queries

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Collation Priority

If there are collation rules applied on the index and the query, then we can set the priority of the collation rule.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const options = { "collation": { "locale": "en_US", "strength": 2 } };
    const cursor = testCollection
      .find({}, options)
      .sort({ "name": -1 });
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We have an options object to set the collation rule with the strength property.

The strength property determines the order of the collation rules we apply.

Collation Query

Collation is supported by find and sort queries.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = testCollection
      .find({ name: "name" }, { collation: { locale: "en" } })
      .sort({ name: 1 });
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

The 2nd argument of find has an object with the collation property to set the collation rules.

We can also set the collation rule with the findOneAndUpdate method:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const db = client.db("test");
    await db.dropCollection('test');
    await db.createCollection("test");
    const testCollection = await db.collection('test');
    await testCollection.createIndex(
      { 'name': 1 },
      { 'collation': { 'locale': 'en' } });
    await testCollection.dropIndexes();
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    testCollection
      .findOneAndUpdate(
        { qty: { $lt: 5 } },
        { $set: { rating: 5 } },
        { collation: { locale: "en" } },
      )
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

The 3rd argument has the collation property set to set the collation rule.

Conclusion

The collation rule priority can be set when we make queries. Also, we can set collation rules when we find, sort or update items.

Categories
MongoDB Node.js Basics

Node.js Basics — Logging with MongoDB

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Logging

The MongoDB Node.js client has a logger built into it.

To use it, we can write:

const { MongoClient, Logger } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    Logger.setLevel("debug");
    await client.connect();
    const db = client.db("test");
    db.dropCollection('test');
    db.createCollection('test');
    const testCollection = await db.collection('test');
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "apples", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = await testCollection.find();
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

to call Logger.setLevel to 'debug' to see all the debug messages when the methods below it are run.

We should see a lot more messages displayed in the console that without the logger.

Filter on a Specific Class

We can filter items when we’re logging so that we don’t see so many items.

For example, we can write:

const { MongoClient, Logger } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    Logger.setLevel("debug");
    Logger.filter("class", ["Db"]);
    await client.connect();
    const db = client.db("test");
    db.dropCollection('test');
    db.createCollection('test');
    const testCollection = await db.collection('test');
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "apples", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = await testCollection.find();
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

The Logger.filter method with the ['Db'] array lets us display messages that are on the 'Db' class.

We can also customize the logger with our own class.

For example, we can write:

const { MongoClient, Logger } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

class CustomLogger {
  constructor() {
    this.logger = new Logger("A");
  }

log() {
    if (this.logger.isInfo()) {
      this.logger.info("logging A", {});
    }
  }
}

async function run() {
  try {
    const customLogger = new CustomLogger();
    customLogger.log();
    await client.connect();
    const db = client.db("test");
    db.dropCollection('test');
    db.createCollection('test');
    const testCollection = await db.collection('test');
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "apples", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = await testCollection.find();
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We created the CustomLogger class and used its log method to do the logging.

Also, we can call setCurrentLogger to set a custom logger function:

const { MongoClient, Logger } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    Logger.setLevel("debug");
    Logger.setCurrentLogger((msg, context) => {
      context['foo'] = 'bar';
      msg = `Hello, World. ${msg}`;
      console.log(msg, context);
    });
    await client.connect();
    const db = client.db("test");
    db.dropCollection('test');
    db.createCollection('test');
    const testCollection = await db.collection('test');
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "apples", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const cursor = await testCollection.find();
    cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

The msg parameter has the message. The context has additional data about the event that’s logged.

Conclusion

We can add a logger to our MongoDB code with the Node.js MongoDB client.

Categories
MongoDB Node.js Basics

Node.js Basics — Specify Which Fields to Return with MongoDB

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Specify Which Fields to Return with MongoDB

We can specify the fields that we want to return for each entry/.

For example, we can wrote:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const projection = { name: 1 };
    const cursor = testCollection.find().project(projection);
    await cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

We call the project method with an object that has the keys that we want to include in the keys.

The value is 1 means we include the given property in the result.

The _id field is returned automatically by default.

So we get:

{ _id: 1, name: 'apples' }
{ _id: 2, name: 'bananas' }
{ _id: 3, name: 'oranges' }
{ _id: 4, name: 'avocados' }

returned.

If we want to disable this, then we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const projection = { _id: 0, name: 1 };
    const cursor = testCollection.find().project(projection);
    await cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

Then we get:

{ name: 'apples' }
{ name: 'bananas' }
{ name: 'oranges' }
{ name: 'avocados' }

We can specify multiple fields in the query.

For example, we can write:

const { MongoClient } = require('mongodb');
const connection = "mongodb://localhost:27017";
const client = new MongoClient(connection);

async function run() {
  try {
    await client.connect();
    const testCollection = await client.db("test").collection('test');
    await testCollection.deleteMany({})
    const result = await testCollection.insertMany([
      { "_id": 1, "name": "apples", "qty": 5, "rating": 3 },
      { "_id": 2, "name": "bananas", "qty": 7, "rating": 1 },
      { "_id": 3, "name": "oranges", "qty": 6, "rating": 2 },
      { "_id": 4, "name": "avocados", "qty": 3, "rating": 5 },
    ]);
    console.log(result)
    const projection = { _id: 0, rating: 1, name: 1 };
    const cursor = testCollection.find().project(projection);
    await cursor.forEach(console.dir);
  } finally {
    await client.close();
  }
}
run().catch(console.dir);

Then, we get:

{ name: 'apples', rating: 3 }
{ name: 'bananas', rating: 1 }
{ name: 'oranges', rating: 2 }
{ name: 'avocados', rating: 5 }

returned.

Conclusion

We can select the fields we return with MongoDB queries.