-
Notifications
You must be signed in to change notification settings - Fork 8
QueryAPI
The package devextreme-query-mongodb exports a function called query
. It accepts a MongoDB collection, a loadOptions structure, and optionally processing options. Here is a simple example:
const MongoClient = require("mongodb").MongoClient;
const query = require("devextreme-query-mongodb");
async function queryData() {
MongoClient.connect("mongodb://localhost:27017/testdatabase", (err, db) => {
const results = await query(db.collection("values"), {
// This is the loadOptions object - pass in any valid parameters
take: 10,
filter: [ "intval", ">", 47 ],
sort: [ { selector: "intval", desc: true }]
});
// Now "results" contains an array of ten or fewer documents from the
// "values" collection that have intval > 47, sorted descendingly by intval.
});
}
In addition to the collection
and loadOptions
parameters, the query
function accepts an optional configuration object. Here is an overview of the available options, please see the sections below the table for details.
Option | Details |
---|---|
replaceIds |
(default: true ) - return _id field values as strings |
summaryQueryLimit |
(default: 100 ) - safety net to protect against overly large numbers of per-group summary queries |
timezoneOffset |
(default: 0 ) - facilitate handling of time zone differences between server and client for date/time field postfixes in filters or group definitions |
caseInsensitiveRegex |
(default: true ) - change case sensitivity of string filter and search criteria |
aggregateOptions |
(default: unset) - specify options for the aggregate calls to the MongoDB collection |
dynamicAggregateOptions |
(default: unset) - dynamically configure options for the aggregate calls to the MongoDB collection |
preferMetadataCount |
(default: false) - not recommended for general use, see description! - prefer metadata based total-count mechanism |
For clarity, a query
call that passes processing options might look like this:
const results = await query(
db.collection('values'),
{
filter: ['intval', '>', 47],
},
{
// these are processing options
replaceIds: false,
timezoneOffset: new Date().getTimezoneOffset(),
}
);
replaceIds
is set to true
by default. The effect of this is that _id
field values are returned as strings, instead of using the MongoDB internal object representation. The default value is set under the assumption that data will be passed on to parts of the application system where the origin of the id values should not be visible. Since MongoDB doesn't have a built-in mechanism (as far as I know) to return id values as strings, there is a certain overhead associated with this approach. In cases where you are going to process the data further using other MongoDB queries, or if you use your own structures for id values, it can increase performance to pass false
for replaceIds
.
summaryQueryLimit
is a safety-net for a situation where group queries are executed to return large result sets, and group summaries are required at the same time. Separate queries need to be executed internally to calculate various summaries, and if this is accidentally done for all groups it can result in an increase in processing time to the extent that other parts of your architecture encounter timeouts. Realistically this shouldn't happen as long as group queries are combined with reasonable take
values. But with certain combinations of flags (server-side grouping and summaries, but no groupPaging
) the Data Grid executes queries that result in this issue. The default summaryQueryLimit
prevents more than 100 summaries from being calculated, which should suffice in most cases. If you want to deactivate this mechanism, set summaryQueryLimit
to 0
(zero).
timezoneOffset
is set to 0
(zero) by default. It is relevant if you use field postfixes like Month
or DayOfWeek
(see loadOptions) for either filtering or grouping. MongoDB stores Date values in UTC time, using the server time zone to convert, and for the aggregation pipeline features that are used by devextreme-query-mongodb, it does not do anything to convert the values back to a client time zone. (There is an outstanding issue recorded for MongoDB to fix this behavior.)
By setting timezoneOffset
to your client offset, you instruct devextreme-query-mongodb to modify the stored Date values by the offset before extracting the Month
, DayOfWeek
... details. The value used for this parameter should have the "format" returned by the function Date.getTimezoneOffset()
. For instance, if your local time is one hour ahead of UTC, you should use -60
for timezoneOffset
.
Note that this feature does not help in situations where your client time zone is different from the server one. In such cases, you need to convert time values on the client before persisting them, and convert them back after querying them.
Note that an issue tracks progress of an update to this feature.
caseInsensitiveRegex
is set to true
by default.
Note that this is a breaking change in 2.0.9.
If the option is true
, all $regex
queries are run with the the i
option to activate case insensitivity. This affects the operators startswith
, endswith
, contains
and notcontains
for filter and search criteria.
Queries executed by devextreme-query-mongodb utilize the MongoDB function collection.aggregate
. The function supports a set of options. Using the aggregateOptions
option, the following options can be configured:
allowDiskUse
maxTimeMS
readConcern
collation
hint
comment
The object passed to aggregateOptions
is filtered to contain only the supported values, but the resulting parameter object is passed directly to each aggregate
call that is executed as part of a devextreme-query-mongodb query process.
Note that any individual call to the devextreme-query-mongodb query
function can result in several calls to collection.aggregate
. The same aggregateOptions
will be passed to all such calls within the context of one query
call.
dynamicAggregateOptions
can be set to a function, which will be called each time a MongoDB collection.aggregate
call is executed. This is the function signature:
...
dynamicAggregateOptions: (identifier, pipeline, collection) => {
}
...
The identifier
parameter can be used to find out which part of the query algorithm is currently being executed. Five different identifiers are currently used:
getCount
queryGroupData
augmentWithSummaries
summary
mainQueryResult
Unfortunately the meaning of each call within the context of the overall query algorithm is difficult to describe, which makes dynamicAggregateOptions
an advanced feature. I recommend reading src/index
js` to fully understand the algorithm.
The return value of dynamicAggregateOptions
is used directly in the following call to collection.aggregate
, but it is first filtered as described above for aggregateOptions
.
Note that only one of aggregateOptions
and dynamicAggregateOptions
can be used at a time. dynamicAggregateOptions
takes preference if included.
Note: Not recommended for general use! Please read the description carefully and make sure you understand the implications if you decide to use this option.
This issue describes research into the performance of different "count" mechanisms. devextreme-query-mongodb requires a "count" algorithm in several scenarios, and specifically the requireTotalCount
load option can result in significant overhead for some queries. However, client components may require the total count to enable paging features.
MongoDB supports a metadata-based count function, but according to docs and tests with the Node driver this function is now deprecated since it doesn't render correct results in all cases.
This issue comment describes the conditions under which the option preferMetadataCount
can be used in spite of the deprecation situation, to benefit from the faster "count" functionality.
Note that the feature may be removed in the future if the MongoDB driver changes.