☝️Small business or a startup? See if you qualify for our special offer.
+
All documentation
  • Introduction
  • Connecting to data source
    1. Supported data sources
    2. Connecting to other data sources
  • Browser compatibility
  • Documentation for older versions
  • Embedding the MongoDB Connector into the server

    This tutorial describes how to embed Flexmonster MongoDB Connector into a Node.js server.

    Alternatively, you can run our ready-to-use sample project.

    Prerequisites

    Step 1. (optional) Create a simple server

    If you already have a server, skip this step.

    Follow the steps below to create a server application using Express.js:

    Step 1.1. Create a folder, navigate to it, and run the following command in the console to generate the package.json file:

    npm init

    Step 1.2. Install the express, cors, and body-parser packages from npm:

    npm install express cors body-parser

    Step 1.3. Then, create a simple server in a .js file (e.g., server.js). Your code should look similar to the following:

    const express = require("express");
    const cors = require("cors");
    const bodyParser = require("body-parser");

    const app = express();

    // Enable CORS if Flexmonster Pivot is running on a different server
    app.use(cors());
    app.use(bodyParser.json());

    let port = 9204;
    app.listen(port, () => {
    console.log(`The server is listening at http://localhost:${port}`)
    });

    Step 2. Install packages for working with MongoDB

    Install Flexmonster MongoDB Connector and the MongoDB driver:

    npm install flexmonster-mongo-connector mongodb@4.17.2

    Note Ensure you have installed MongoDB version 4.17.2 or earlier, as our Connector is not compatible with the later MongoDB versions.

    Step 3. Create and configure a module for the Flexmonster’s requests

    Step 3.1. Create a module that will handle the Flexmonster’s requests. In this tutorial, we will create the module in a mongo.js file.

    Step 3.2. Include the following libraries in mongo.js:

    const { MongoClient } = require("mongodb");
    const fm_mongo_connector = require("flexmonster-mongo-connector");

    Step 3.3. Set up a connection with your MongoDB database:

    // Connection string to the Flexmonster’s cluster
    const uri = "mongodb://read:only@olap.flexmonster.com:27017"
    const client = new MongoClient(uri);
    let database = null; // The database instance

    async function connectDB() {
    try {
    await client.connect();
    // Flexmonster’s sample database
    database = client.db("flexmonster");
    } catch (err) {
    // Your error handler
    }
    }

    connectDB();

    Step 3.4. Create the MongoDB Connector instance:

    let mongoConnector= null; // The Connector instance

    // The Connector’s configurations
    const config = {
    cacheEnabled: true,
    cacheMemoryLimit: 100,
    cacheTimeToLive: 120,
    logsEnabled: true
    };

    async function connectDB() {
    try {
    await client.connect();
    // Flexmonster’s sample database
    database = client.db("flexmonster");
    mongoConnector = new fm_mongo_connector.MongoDataAPI(config);
    } catch (err) {
    // Your error handler
    }
    }

    connectDB();

    To learn more about the Connector’s config, see the Configuring the Connector guide.

    Step 3.5. Export the mongo module so the server can use it:

    module.exports = mongo;

    Step 3.6. Include the mongo.js module into your server (e.g., server.js):

    app.use('/mongo', require('./mongo.js'));

    Now, when Flexmonster starts sending requests to <server_url/mongo>, they will be processed by mongo.js.

    In the next steps, we will handle all Flexmonster requests.

    Step 4. Create endpoints

    The mongo module must provide the endpoints that handle POST requests from Flexmonster.

    Flexmonster sends 4 types of requests:

    In the mongo.js file, create the endpoints for the requests using Express.js:

    const mongo = require('express').Router();
    // Other code

    mongo.post("/handshake", async (req, res) => {});
    mongo.post("/fields", async (req, res) => {});
    mongo.post("/members", async (req, res) => {});
    mongo.post("/select", async (req, res) => {});

    As you can see, the request's name corresponds to its endpoint. For example, all /select requests are sent to the /select endpoint.

    In the next steps, you will learn how to handle each request.

    Step 5. Handle the /handshake request

    First, Flexmonster sends the /handshake request to establish communication with the server. The component includes its version in the request and expects a response with the custom data source API version implemented by the server.

    In mongo.js, handle the /handshake request. Your code should look similar to the following:

    mongo.post("/handshake", async (req, res) => {
    try {
    res.json({ version: mongoConnector.API_VERSION });
    } catch (err) {
    // Your error handler
    }
    });

    mongoConnector.API_VERSION contains the custom data source API version implemented by the MongoDB Connector.

    Step 6. Handle the /fields request

    Now you need to handle a /fields request. It is sent to <url>/fields

    To handle this request, use the getSchema method:

    mongo.post("/fields", async (req, res) => {
    try {
    const result = await mongoConnector.getSchema(database, req.body.index);
    res.json(result);
    } catch (err) {
    // Your error handler
    }
    });

    When Flexmonster Pivot successfully receives a response to the /fields request, it shows the Field List with all of the available fields.

    Step 7. Handle the /members request

    The next request to handle is the request for the field’s members that is sent to <url>/members.

    Ways to handle the /members request depend on whether multilevel hierarchies are configured on the client or not.

    If multilevel hierarchies are not configured

    If multilevel hierarchies are not configured on the client, the /members request can be handled using the getMembers method as follows:

    mongo.post("/members", async (req, res) => {
    try {
    const result = await mongoConnector.getMembers(
    database,
    req.body.index,
    { field: req.body.field },
    { page: req.body.page, pageToken: req.body.pageToken }
    );
    res.json(result);
    } catch (err) {
    // Your error handler
    }
    });

    If multilevel hierarchies are configured

    If multilevel hierarchies are configured on the client, the /members request can be handled using the getMembers method as follows:

    mongo.post("/members", async (req, res) => {
     try {
        const result = await mongoConnector.getMembers(
         database,
    req.body.index,
         { field: req.body.field, filter: req.body.filter },
         { page: req.body.page, pageToken: req.body.pageToken }
    );
       res.json(result);
     } catch (err) {
       // Your error handler
     }
    });

    Notice req.body.filter in the following code line:

    { field: req.body.field, filter: req.body.filter },

    The req.body.filter request parameter contains filters for hierarchical data. Flexmonster includes them into the /members request when multilevel hierarchies are configured in the component. These filters should be passed to the getMembers method.

    When Flexmonster Pivot successfully receives the response to this request, you will be able to select a string field for rows or columns and retrieve its members.

    Step 8. Handle the /select request

    When a field is selected for rows or columns and a numeric field is selected for measures in the Field List, the /select request for the pivot table is sent to the endpoint <url>/select. It can be handled using the getSelectResult method:

    mongo.post("/select", async (req, res) => {
    try {
    const result = await mongoConnector.getSelectResult(
    database, req.body.index, req.body.query,
    { page: req.body.page, pageToken: req.body.pageToken });
    res.json(result);
    } catch (err) {
    // Your error handler
    }
    });

    When Flexmonster successfully receives the response to this kind of /select request, a pivot table with the received data is shown.

    Note The /select requests for the flat table and the drill-through view can also be handled using the getSelectResult method.

    Step 9. Run the server

    Run your server with the following command:

    node server.js

    Step 10. Configure the report

    In Flexmonster, the report should be configured as follows:

    const pivot = new Flexmonster({
    container: "pivotContainer",
    toolbar: true,
    report: {
    dataSource: {
    type: "api",
    url: "http://localhost:9204/mongo"), // A path to API endpoints
    index: "fm-product-sales" // Flexmonster’s collection name
    }
    }
    });

    Check out the full list of Flexmonster properties used to connect to MongoDB.

    To see Flexmonster with the data from your MongoDB database, open a page with Flexmonster in the browser.

    List of supported configuration parameters

    When connecting to data from the MongoDB, you can use the following properties to configure the DataSourceObject:

    List of properties
    Property/TypeDescription
    type
    String
    The data source type. When connecting to data from MongoDB, set the type to "api".
    url
    String
    The URL to the server’s endpoint that handles Flexmonster's custom data source API requests.
    index
    String
    The collection name.
    mapping
    MappingObject | String
    optional Defines how fields from the data source are treated and presented within the component. For example, you can specify the field’s captions, define a type for a field, configure multilevel hierarchies, etc. Read more in the Mapping guide.
    It can be either an inline MappingObject or a URL to a JSON file with the mapping Live example.
    requestHeaders
    Object
    optional Adds custom request headers. Consists of "key": "value" pairs, where "key" is a header name and "value" is its value Live example.
    Note The requestHeaders property is not saved when obtaining the report via save() and getReport() API calls.
    singleendpoint
    Boolean
    optional When set to true, all custom data source API requests are sent to a single endpoint specified in the url property.
    Default value: false.
    withCredentials
    Boolean
    optional Indicates whether cross-site Access-Control requests should be made using credentials such as authorization headers (true) or not (false). For more details, refer to MDN web docs.
    Setting the withCredentials flag to true is recommended when using Windows authentication and other types of server authentication. When set to false, the browser does not ask for credentials and does not include them in outgoing requests.
    Default value: false.
    concurrentRequests
    Boolean
    optional When set to false, Flexmonster sends a request for each expand/drill-down separately and waits for the server’s response before sending a new request. This can result in slow performance when there are a lot of expands/drill-downs in the report.
    When the concurrentRequests is true, Flexmonster sends requests for expands/drill-downs of a particular level simultaneously. To get the best performance, enable the HTTP/2 protocol on your server.
    Default value: false.

    See also