Select lists of suggestions or ngrams with /api or /api/ngrams respectively, JSONify ngrams response
parent
c9c03d3104
commit
b9d5b78a2e
|
@ -19,8 +19,9 @@ if (
|
|||
) throw new DatabaseConnectionError(
|
||||
"Some Postgres environment variables weren't found. Please configure them in the .env file."
|
||||
);
|
||||
let sslmode = process.env.POSTGRES_SSLMODE === "require";
|
||||
const connection_string = `postgresql://${process.env.POSTGRES_USERNAME}:${process.env.POSTGRES_PASSWORD}@${process.env.POSTGRES_HOST}:${process.env.POSTGRES_PORT}/${process.env.POSTGRES_DB_NAME}?ssl=${sslmode}`;
|
||||
let connection_string = `postgresql://${process.env.POSTGRES_USERNAME}:${process.env.POSTGRES_PASSWORD}@${process.env.POSTGRES_HOST}:${process.env.POSTGRES_PORT}/${process.env.POSTGRES_DB_NAME}`;
|
||||
if (process.env.POSTGRES_SSLMODE === "require")
|
||||
connection_string += "?ssl=true";
|
||||
const db = pgp(connection_string);
|
||||
|
||||
module.exports = db;
|
|
@ -1,6 +1,9 @@
|
|||
const validate = require("../validate.js");
|
||||
const { ParameterizedQuery: PQ } = require("pg-promise");
|
||||
|
||||
const DEFAULT_ITEM_LIMIT = 25;
|
||||
const MAX_ITEM_LIMIT = 100;
|
||||
|
||||
const db = require("./connection.js");
|
||||
|
||||
async function querySuggestions(handle, threshold = 0) {
|
||||
|
@ -18,16 +21,15 @@ async function querySuggestions(handle, threshold = 0) {
|
|||
return { error: { name: error.name, message: error.message } };
|
||||
});
|
||||
|
||||
if (result?.["error"])
|
||||
return result;
|
||||
if (result?.["error"]) return result;
|
||||
|
||||
console.log(result);
|
||||
|
||||
|
||||
const data = {
|
||||
"handle": handle,
|
||||
"suggestions": result
|
||||
handle: handle,
|
||||
suggestions: result,
|
||||
};
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -35,18 +37,83 @@ async function queryNgrams(handle) {
|
|||
await validate.checkHandle(handle);
|
||||
|
||||
const query = new PQ({
|
||||
text: "SELECT * FROM oapen_suggestions.ngrams WHERE handle = $1",
|
||||
text: `SELECT handle, "name", thumbnail, created_at, updated_at,
|
||||
array_agg(
|
||||
JSON_BUILD_OBJECT(
|
||||
'ngram', ngram.ngram,
|
||||
'count', ngram.count
|
||||
)
|
||||
) as ngrams
|
||||
FROM oapen_suggestions.ngrams, UNNEST(ngrams) as ngram
|
||||
WHERE handle = $1
|
||||
GROUP BY handle;`,
|
||||
values: [handle],
|
||||
});
|
||||
|
||||
return db.one(query).catch((error) => {
|
||||
return { error: { name: error.name, message: error.message } };
|
||||
});
|
||||
}
|
||||
|
||||
// return await db.any(query);
|
||||
async function queryManySuggestions(
|
||||
threshold = 0,
|
||||
limit = DEFAULT_ITEM_LIMIT,
|
||||
offset = 0
|
||||
) {
|
||||
if (threshold < 0) threshold = 0;
|
||||
if (limit > validate.MAX_ITEM_LIMIT) {
|
||||
limit = validate.MAX_ITEM_LIMIT;
|
||||
} else if (limit < 1) {
|
||||
limit = 1;
|
||||
}
|
||||
if (offset < 0) offset = 0;
|
||||
|
||||
const query = new PQ({
|
||||
text: `SELECT suggestion AS handle, score
|
||||
FROM oapen_suggestions.suggestions
|
||||
WHERE score >= $1
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $2 OFFSET $3;`,
|
||||
values: [threshold, limit, offset],
|
||||
});
|
||||
|
||||
return db.query(query).catch((error) => {
|
||||
return { error: { name: error.name, message: error.message } };
|
||||
});
|
||||
}
|
||||
|
||||
async function queryManyNgrams(limit = DEFAULT_ITEM_LIMIT, offset = 0) {
|
||||
if (limit > validate.MAX_ITEM_LIMIT) {
|
||||
limit = validate.MAX_ITEM_LIMIT;
|
||||
} else if (limit < 1) {
|
||||
limit = 1;
|
||||
}
|
||||
if (offset < 0) offset = 0;
|
||||
|
||||
const query = new PQ({
|
||||
text: `SELECT handle, "name", thumbnail, created_at, updated_at,
|
||||
array_agg(
|
||||
JSON_BUILD_OBJECT(
|
||||
'ngram', ngram.ngram,
|
||||
'count', ngram.count
|
||||
)
|
||||
) as ngrams
|
||||
FROM oapen_suggestions.ngrams, UNNEST(ngrams) as ngram
|
||||
GROUP BY handle
|
||||
ORDER BY created_at
|
||||
LIMIT $1 OFFSET $2;
|
||||
`,
|
||||
values: [limit, offset],
|
||||
});
|
||||
|
||||
return db.query(query).catch((error) => {
|
||||
return { error: { name: error.name, message: error.message } };
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
querySuggestions,
|
||||
queryNgrams,
|
||||
queryManySuggestions,
|
||||
queryManyNgrams,
|
||||
};
|
||||
|
|
|
@ -59,4 +59,67 @@ router.get("/:handle([0-9]+.[0-9]+.[0-9]+/[0-9]+)/ngrams", async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
try {
|
||||
let threshold = parseInt(req.query.threshold) || 0;
|
||||
if (threshold < 0) threshold = 0;
|
||||
let limit = parseInt(req.query.limit) || validate.DEFAULT_ITEM_LIMIT;
|
||||
let offset = parseInt(req.query.offset) || 0;
|
||||
if (limit > validate.MAX_ITEM_LIMIT) {
|
||||
limit = validate.MAX_ITEM_LIMIT;
|
||||
} else if (limit < 1) {
|
||||
limit = 1;
|
||||
}
|
||||
if (offset < 0) offset = 0;
|
||||
|
||||
|
||||
let responseData = await data.queryManySuggestions(threshold, limit, offset);
|
||||
|
||||
if (
|
||||
responseData.error &&
|
||||
responseData.error.name === pgp.errors.QueryResultError.name
|
||||
) {
|
||||
return res.status(404).json({ error: responseData.error.message });
|
||||
} else if (responseData.error) {
|
||||
return res.status(500).json(responseData);
|
||||
}
|
||||
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
return res.status(200).json(responseData);
|
||||
} catch (e) {
|
||||
return res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
})
|
||||
|
||||
router.get("/ngrams", async (req, res) => {
|
||||
try {
|
||||
let limit = parseInt(req.query.limit) || validate.DEFAULT_ITEM_LIMIT;
|
||||
let offset = parseInt(req.query.offset) || 0;
|
||||
if (limit > validate.MAX_ITEM_LIMIT) {
|
||||
limit = validate.MAX_ITEM_LIMIT;
|
||||
} else if (limit < 1) {
|
||||
limit = 1;
|
||||
}
|
||||
if (offset < 0) offset = 0;
|
||||
|
||||
let responseData = await data.queryManyNgrams(limit, offset);
|
||||
|
||||
if (
|
||||
responseData.error &&
|
||||
responseData.error.name === pgp.errors.QueryResultError.name
|
||||
) {
|
||||
return res.status(404).json({ error: responseData.error.message });
|
||||
} else if (responseData.error) {
|
||||
return res.status(500).json(responseData);
|
||||
}
|
||||
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
|
||||
return res.status(200).json(responseData);
|
||||
} catch (e) {
|
||||
return res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = router;
|
||||
|
|
|
@ -7,6 +7,9 @@ class UserError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
const MAX_ITEM_LIMIT = 100;
|
||||
const DEFAULT_ITEM_LIMIT = 25;
|
||||
|
||||
// RegEx to match formatting of handle
|
||||
const handleRegExpression = new RegExp("([0-9]+.[0-9]+.[0-9]+/[0-9]+)");
|
||||
|
||||
|
@ -24,4 +27,6 @@ let checkHandle = async (handle) => {
|
|||
|
||||
module.exports = {
|
||||
checkHandle,
|
||||
MAX_ITEM_LIMIT,
|
||||
DEFAULT_ITEM_LIMIT
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue