Flexmonster Software License Agreement (“Agreement”) has been revised and is effective as of January 8, 2025.
The following modifications were made:
The modified version of Agreement is available here.
Downloading, installing, and/or continuing to use Flexmonster Software after January 8, 2025, constitutes Licensee’s acceptance of the terms and conditions of the modified version of Agreement. If Licensee does not agree to any of these terms and conditions, they must cease using Flexmonster Software and must not download, install, use, access, or continue to access Flexmonster Software. By continuing to use Flexmonster Software or renewing the license or maintenance after the effective date of these modifications to Agreement, Licensee accepts and agrees to be bound by the terms and conditions of the modified Agreement.
This tutorial describes how to embed Flexmonster MongoDB Connector into a Node.js server.
Alternatively, you can run our ready-to-use sample project.
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}`)
});
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.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.
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.
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.
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.
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 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 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.
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.
Run your server with the following command:
node server.js
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.
When connecting to data from the MongoDB, you can use the following properties to configure the DataSourceObject:
Property/Type | Description |
---|---|
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 . |