Properties fragment query has no effect - node.js

I am using the Node.js API provided by MarkLogic to read values from the URI lexicon using the following code
const marklogic = require("marklogic");
const dbConn = require("../config/ml-connections");
const dbRead = marklogic.createDatabaseClient(dbConn.restReader);
const dbWrite = marklogic.createDatabaseClient(dbConn.restWriter);
const qb = marklogic.queryBuilder;
const vb = marklogic.valuesBuilder;
let termOption: string = 'exact';
let status: string = 'active';
let startDateTime = '2022-08-01T00:00:00Z';
let endDateTime = '2022-09-01T00:00:00Z';
let start = 1;
let end = 10;
if (status === 'all') {
termOption = 'wildcarded';
status = '*';
}
dbRead.values.read(
vb.fromIndexes(vb.uri())
.where(
qb.and(
qb.value('status', status, qb.termOptions(termOption)),
qb.propertiesFragment(
qb.and(
qb.range(qb.qname('prop:last-modified'), qb.datatype('dateTime'), '>=', startDateTime),
qb.range(qb.qname('prop:last-modified'), qb.datatype('dateTime'), '<=', endDateTime)
)
)
)
)
.slice(start, end)
.withOptions({values: ['descending']})
)
.result()
.then(function (resultObject) {
let uris: string[] = [];
if (resultObject['values-response'].tuple) {
for (const row of resultObject['values-response'].tuple) {
uris.push(row['distinct-value'][0]);
}
}
return uris;
})
This code works, but the properties fragment query here has no effect on the result of the program. What could be wrong?
PS: Ignore syntax and obvious coding errors, if any, as the code works. MarkLogic version 10.0-9.4.

Related

How to get quantity of duplicates in array nodejs

I'm trying to get the quantity of for example: DragonBall, it would return x3 or Featured it would return x2 etc, however I have tried this method with just the spammed response of 2
let data = mockdata.forEach(function (i) {
count[i] = (count[i] || 0) + 1;
console.log(count[i] = (count[i] || 0) + 1)
});
[
'Daily',
'DragonBall1B',
'DragonBall2B',
'DragonBall3B',
'Featured',
'Featured2',
'SquadOrigins',
'SquadOrigins2'
]
API used to retrieve the above information:
https://fortnitecontent-website-prod07.ol.epicgames.com/content/api/pages/fortnite-game/shop-sections
A regular expression can remove the first instance of digits (along with whatever follows) to get you to the key you're interested in grouping on.
const mockdata = [
'Daily',
'DragonBall1B',
'DragonBall2B',
'DragonBall3B',
'Featured',
'Featured2',
'SquadOrigins',
'SquadOrigins2'
]
const count = {};
mockdata.forEach((str) => {
const key = str.replace(/\d+.*/, '');
count[key] = (count[key] || 0) + 1;
});
console.log(count.DragonBall);
const arr = [
'Daily',
'DragonBall1B',
'DragonBall2B',
'DragonBall3B',
'Featured',
'Featured2',
'SquadOrigins',
'SquadOrigins2'
]
const count = {};
arr.forEach((str) => {
const key = str.replace(/\d+.*/, "");
count[key] = (count[key] || 0) + 1;
});
let val = Object.entries(count);
let itemName;
let itemNum;
let result = [];
for (var i in val) {
itemName = val[i][0];
itemNum = val[i][1];
result += `${itemName} (x${itemNum})\n`;
}
console.log(result);

how to save data downloaded in a loop to json

I have a problem. I got one to save the data called in a loop to an empty json. It's about "eventsPolygon". One args with index 0 will have to be written to JSONA. How to do it?
async function main() {
console.log("Start checking rewards")
const currentBlockNumberPolygon = await maticProvider.getBlockNumber() - 1
const currentBlockNumberBsc = await bscProvider.getBlockNumber() - 1
const oldestBlockNumberPolygon = 22939848
const oldestBlockNumberBsc = 13763979
const eventFilterPolygon = Missions.filters.RewardToPay()
const eventFilterBsc = Rewards.filters.RewardPayed()
let eventsPolygon = []
let eventsBsc = []
for(let i = oldestBlockNumberPolygon; i < currentBlockNumberPolygon-10000; i+=10000) {
const eventsLoop = await Missions.queryFilter(eventFilterPolygon, i, i+10000)
eventsPolygon = eventsPolygon.concat(eventsLoop)
console.log(i)
}
//for(let i = oldestBlockNumberBsc; i < currentBlockNumberBsc-10000; i+=10000) {
//const eventsLoop = await Rewards.queryFilter(eventFilterBsc, i, i+10000)
// eventsBsc = eventsBsc.concat(eventsLoop)
//console.log(i)
//}
console.log('a')
}
when iterating if your certain that you need the zero index you could just make a condition inside your loop, if(i == 0){wanted action}

Global variable not updated

I have a problem in this code.
I am trying to parse an excel file but cannot make the parent relationship.
Parent records are created successfully, child records are also created, but parent_id is always 0
let parent_id = 0; // this var not updated!!!
let workbook = new Excel.Workbook()
workbook = await workbook.xlsx.readFile(location)
workbook.worksheets[0].eachRow(async (row) => {
console.log(parent_id) // each time 0,0,0,0
const name = row.getCell(1).value
const obj = {
name,
number: row.getCell(2).value,
parent_id: name ? null : parent_id
}
if(obj.number && Number(obj.number) == obj.number){
const node = await LeadNode.create(obj)
if(name){
parent_id = node.id
console.log(parent_id) // work here 1,2,3,4,5
}
}
});
db screen
The problem is caused by .eachRow() not awaiting for your callback to finish.
If you somehow make the callback not async, it would work. This means that you'll have to call this await LeadNode.create(obj) outside the callback.
Possible solution: create an array of obj, then iterate over them and call the await LeadNode(...). Something like:
let parent_id = 0; // this var not updated!!!
let workbook = new Excel.Workbook()
workbook = await workbook.xlsx.readFile(location)
const objs = [];
workbook.worksheets[0].eachRow((row) => {
console.log(parent_id) // each time 0,0,0,0
const name = row.getCell(1).value
const obj = {
name,
number: row.getCell(2).value,
}
objs.push(obj);
});
for (const obj of objs){
if(obj.number && Number(obj.number) == obj.number){
obj.parent_id = obj.name ? null : parent_id
const node = await LeadNode.create(obj)
if(name){
parent_id = node.id
console.log(parent_id) // work here 1,2,3,4,5
}
}
}

Async/Await Node-Postgres Queries Within ForEach Loops

EDIT: I'm using node v8.0.0
I just started learning how to access SQL databases with node-postgres, and I'm having a little bit of trouble accessing multiple databases to collect the data in a work able format, particularly with executing multiple queries within forEach loops. After a few tries, I'm trying async/await, but I get the following error:
await client.connect()
^^^^^^
SyntaxError: Unexpected identifier
When I tried using a pool or calling .query sequentially, I would get something along the lines of
1
[]
could not connect to postgres Error: Connection terminated
Here is an abbreviated version of my code:
const { Client } = require('pg');
const moment = require('moment');
const _ = require('lodash');
const turf = require('#turf/turf');
const connString = // connection string
var collected = []
const CID = 300
const snaptimes = // array of times
var counter=0;
const client = new Client(connString);
function createArray(i,j) {
// return array of i arrays of length j
}
await client.connect()
snaptimes.forEach(function(snaptime){
var info = {}; // an object of objects
// get information at given snaptime from database 1
const query1 = // parametrized query selecting two columns from database 1
const result1 = await client.query(query1, [CID,snaptime]);
var x = result1.rows;
for (var i = 0; i < x.length; i++) {
// store data from database 1 into info
// each row is an object with two fields
}
// line up subjects on the hole
const query2 = // parametrized query grabbing JSON string from database 2
const result2 = await client.query(query2, [CID,snaptime]);
const raw = result2.rows[0].JSON_col;
const line = createArray(19,0); // an array of 19 empty arrays
for (var i = 0; i < raw.length; i++) {
// parse JSON object and record data into line
}
// begin to collect data
var n = 0;
var g = 0;
// walk down the line
for (var i = 18; i > 0; i--) {
// if no subjects are found at spot i, do nothing, except maybe update g
if ((line[i] === undefined || line[i].length == 0) && g == 0){
g = i;
} else if (line[i] !== undefined && line[i].length != 0) {
// collect data for each subject if subjects are found
line[i].forEach(function(subject){
const query 3 = // parametrized query grabbing data for each subject
const result3 = await client.query(query3,[CID,subject,snaptime]);
x = result3.rows;
const y = moment(x[0].end_time).diff(moment(snaptime),'minutes');
var yhat = 0;
// the summation over info depends on g
if (g===0){
for (var j = i; j <= 18; j++){
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
} else {
for (var j = i; j <= 18; j++){
if (i<j && j<g+1) {
yhat = moment.duration(info[j].field2).add(yhat,'m').asMinutes();
} else {
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
}
}
collected.push([y,yhat,n,i]);
});
}
n+=line[i].length;
g=0;
}
// really rough work-around I once used for printing results after a forEach of queries
counter++;
if (counter===snaptimes.length){
console.log(counter);
console.log(collected);
client.end();
}
});
The problem is caused by your forEach callback not being async:
snaptimes.forEach(function(snaptime){
should be:
snaptimes.forEach(async function (snaptime) {
for the await to be recognizable at all.
Keep in mind that an async function returns immediately and it returns a promise that gets eventually resolved by return statements of the async function (or rejected with uncaught exceptions raised inside the async function).
But also make sure your Node version supports async/await:
Since Node 7.6 it can be used with no --harmony flag.
In Node 7.x before 7.6 you have to use the --harmony flag.
It was not available in Node before 7.0.
See: http://node.green/#ES2017-features-async-functions
Also note that you can use await only inside of functions declared with the async keyword. If you want to use it in the top level of your script or module then you need to wrap it in an immediately invoked function expression:
// cannot use await here
(async () => {
// can use await here
})();
// cannot use await here
Example:
const f = () => new Promise(r => setTimeout(() => r('x'), 500));
let x = await f();
console.log(x);
prints:
$ node t1.js
/home/rsp/node/test/prom-async/t1.js:3
let x = await f();
^
SyntaxError: Unexpected identifier
but this:
const f = () => new Promise(r => setTimeout(() => r('x'), 500));
(async () => {
let x = await f();
console.log(x);
})();
prints:
$ node t2.js
x
after 0.5s delay, as expected.
On versions of Node that don't support async/await the first (incorrect) example will print:
$ ~/opt/node-v6.7.0/bin/node t1.js
/home/rsp/node/test/prom-async/t1.js:3
let x = await f();
^
SyntaxError: Unexpected identifier
and the second (correct) example will print a different error:
$ ~/opt/node-v6.7.0/bin/node t2.js
/home/rsp/node/test/prom-async/t2.js:3
(async () => {
^
SyntaxError: Unexpected token (
It's useful to know because Node versions that don't support async/await will not give you a meaningful error like "async/await not supported" or something like that, unfortunately.
Make sure that you should use async block outside like:
async function() {
return await Promise.resolve('')
}
And it is default supported after node 7.6.0. Before 7.6.0, you should use --harmony option to work for it.
node -v first to check your version.
First of all, you don't know enough about async-await just yet. don't worry, it's actually quite easy; but you need to read the documentation to be able to use that stuff.
More to the point, the problem with your code is that you can only await inside async functions; you're doing that outside of any function.
First of all, here's the solution that is closest to the code you wrote:
const { Client } = require('pg');
const moment = require('moment');
const _ = require('lodash');
const turf = require('#turf/turf');
const connString = // connection string
var collected = []
const CID = 300
const snaptimes = // array of times
var counter=0;
const client = new Client(connString);
function createArray(i,j) {
// return array of i arrays of length j
}
async function processSnaptime (snaptime) {
var info = {}; // an object of objects
// get information at given snaptime from database 1
const query1 = // parametrized query selecting two columns from database 1
const result1 = await client.query(query1, [CID,snaptime]);
var x = result1.rows;
for (var i = 0; i < x.length; i++) {
// store data from database 1 into info
// each row is an object with two fields
}
// line up subjects on the hole
const query2 = // parametrized query grabbing JSON string from database 2
const result2 = await client.query(query2, [CID,snaptime]);
const raw = result2.rows[0].JSON_col;
const line = createArray(19,0); // an array of 19 empty arrays
for (var i = 0; i < raw.length; i++) {
// parse JSON object and record data into line
}
// begin to collect data
var n = 0;
var g = 0;
// walk down the line
for (var i = 18; i > 0; i--) {
// if no subjects are found at spot i, do nothing, except maybe update g
if ((line[i] === undefined || line[i].length == 0) && g == 0){
g = i;
} else if (line[i] !== undefined && line[i].length != 0) {
// collect data for each subject if subjects are found
line[i].forEach(function(subject){
const query 3 = // parametrized query grabbing data for each subject
const result3 = await client.query(query3,[CID,subject,snaptime]);
x = result3.rows;
const y = moment(x[0].end_time).diff(moment(snaptime),'minutes');
var yhat = 0;
// the summation over info depends on g
if (g===0){
for (var j = i; j <= 18; j++){
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
} else {
for (var j = i; j <= 18; j++){
if (i<j && j<g+1) {
yhat = moment.duration(info[j].field2).add(yhat,'m').asMinutes();
} else {
yhat = moment.duration(info[j].field1).add(yhat,'m').asMinutes();
}
}
}
collected.push([y,yhat,n,i]);
});
}
n+=line[i].length;
g=0;
}
// really rough work-around I once used for printing results after a forEach of queries
counter++;
if (counter===snaptimes.length){
console.log(counter);
console.log(collected);
}
}
async function run () {
for (let snaptime of snaptimes) {
await processSnaptime(snaptime);
}
}
/* to run all of them concurrently:
function run () {
let procs = [];
for (let snaptime of snaptimes) {
procs.push(processSnaptime(snaptime));
}
return Promise.all(procs);
}
*/
client.connect().then(run).then(() => client.end());
client.connect returns a promise and I use then to call run once it's resolved. When that part is over, client.end() can be called safely.
run is an async function, therefore it can use await to make the code more readable. The same goes for processSnaptime.
Of course I can't actually run your code, so I can only hope I didn't make any mistakes.

NodeJs : Any way to bypass querystring.stringify with empty Object?

I am working currently on a project that requires to send custom GET HTTP requests.
I am using the default querystring builder : the Documentation
const querystring = require('querystring');
The problem is for Object (probably also for empty array) such as
extendTypes={}
is serialiazed as :
extendTypes=
The expected result :
extendTypes={}
or its URI encoded version :
extendTypes%3D%7B%7D
So , how can I ever hope to do that ? If It is impossible with the in-builded module, which one could do what I want.
Here is my full code if you want :
function generateGetRequest(dataMap, url) {
let queryParams = {};
let uriParams = {};
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object || value instanceof Array) {
uriParams[key] = value;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let queryParamsUri = querystring.stringify(uriParams);
console.log(queryParamsUri);
let finalUrl = url + ( (Object.keys(uriParams).length > 0) ? "?" + queryParamsUri : "");
}
I finally found a workaround , if someone wants to know :
let request = require("superagent");
function generateGetRequest(dataMap, url) {
let queryParams = {};
let queryParamsUri = "";
let isFirstParam = true;
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object) {
// Workaround for empty object or array = https://github.com/nodejs/node/issues/12234
queryParamsUri += ((!isFirstParam) ? "&": "") + key + "=" + JSON.stringify(value);
// for next call
isFirstParam = false;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let finalUrl = url + ( (!isFirstParam) ? "?" + queryParamsUri : "");
return request
.get(finalUrl)
.query(queryParams);
}

Resources