util = {
const API_ROOT = "https://api.datacommons.org";
const API_ENDPOINTS = {
query: "/query",
get_property_labels: "/node/property-labels",
get_property_values: "/node/property-values",
get_triples: "/node/triples",
get_places_in: "/node/places-in",
get_related_places: "/node/related-places",
get_stats: "/bulk/stats",
get_stat_value: "/stat/value",
get_stat_series: "/stat/series",
get_stat_all: "/stat/all"
};
const MAX_LIMIT = 100;
const QUERY_BATCH_SIZE = 500;
async function _post(path, data = {}) {
const url = API_ROOT + path;
console.log(
`_post POST to: ${path} with data: ${JSON.stringify(
data
)} url is: ${url}`,
data
);
const headers = { "Content-Type": "application/json" };
const apiKey = "AIzaSyCTI4Xz-UW_G2Q2RfknhcfdAnTHq5X5XuI";
if (apiKey) {
headers["x-api-key"] = apiKey;
}
try {
const resp = await axios({
url: url,
method: "post",
data: data,
headers: headers
});
console.log(`_post resp was: ${resp}`);
if (resp.status !== 200) {
throw new Error(
`${resp.status}: +++ ${resp.statusText}\n${resp.data.message}`
);
}
return resp.data;
} catch (error) {
if (error.response) {
throw new Error(
`${error.response.status}: --- ${error.response.statusText}\n${error.response.data.message}`
);
} else {
throw error;
}
}
}
async function sendRequest(url, data) {
console.log(`sr ${url}`);
console.log(`${JSON.stringify(data)}`);
const headers = { "Content-Type": "application/json" };
const apiKey = "AIzaSyCTI4Xz-UW_G2Q2RfknhcfdAnTHq5X5XuI"; // default public limited
if (apiKey) {
headers["x-api-key"] = apiKey;
}
try {
const resp = await axios({
url: url,
method: "post",
data: data,
headers: headers
});
if (resp.status !== 200) {
throw new Error(
`${resp.status}: +++ ${resp.statusText}\n${resp.data.message}`
);
}
return resp.data;
} catch (error) {
if (error.response) {
throw new Error(
`${error.response.status}: --- ${error.response.statusText}\n${error.response.data.message}`
);
} else {
throw error;
}
}
}
/* PYTHON WAS: def _send_request(req_url,
req_json={},
compress=False,
post=True,
use_payload=True):
""" Sends a POST/GET request to req_url with req_json, default to POST.
Returns:
The payload returned by sending the POST/GET request formatted as a dict.
"""
headers = {'Content-Type': 'application/json'} */
function _getDirection(isOut) {
return isOut ? "out" : "in";
}
async function properties(nodes, isOut = true) {
const resp = await _post(`/v1/bulk/properties/${_getDirection(isOut)}`, {
nodes
});
const result = {};
for (const item of resp.data || []) {
const node = item.node;
const properties = item.properties || [];
result[node] = properties;
}
return result;
}
async function propertyValues(nodes, property, isOut = true) {
const resp = await _post(
`/v1/bulk/property/values/${_getDirection(isOut)}`,
{ nodes, property }
);
const result = {};
for (const item of resp.data || []) {
const node = item.node;
const values = item.values || [];
result[node] = [];
for (const v of values) {
if ("dcid" in v) {
result[node].push(v.dcid);
} else {
result[node].push(v.value);
}
}
}
return result;
}
async function triples(nodes, isOut = true) {
const resp = await _post(`/v1/bulk/triples/${_getDirection(isOut)}`, {
nodes
});
const result = {};
for (const item of resp.data || []) {
const node = item.node;
const triples = item.triples || {};
result[node] = {};
for (const [property, otherNodes] of Object.entries(triples)) {
result[node][property] = otherNodes.nodes || [];
}
}
return result;
}
// part 2
async function getPropertyLabels(dcids, out = true) {
// Filter out NaN values and generate the request payload
dcids = dcids.filter((v) => v === v);
const url = API_ROOT + API_ENDPOINTS.get_property_labels;
const payload = await sendRequest(url, { dcids });
// Return the results based on the orientation
const results = {};
for (const dcid of dcids) {
if (out) {
results[dcid] = payload[dcid].outLabels;
} else {
results[dcid] = payload[dcid].inLabels;
}
}
return results;
}
async function getPropertyValues(
dcids,
prop,
out = true,
valueType = null,
limit = MAX_LIMIT
) {
// Filter out NaN values and prepare the request payload
dcids = dcids.filter((v) => v === v);
const direction = out ? "out" : "in";
const reqJson = {
dcids,
property: prop,
limit,
direction
};
if (valueType) {
reqJson.value_type = valueType;
}
// Send the request
const url = API_ROOT + API_ENDPOINTS.get_property_values;
const payload = await sendRequest(url, reqJson);
// Create the result format for when dcids is provided as a list
const uniqueResults = new Map();
for (const dcid of dcids) {
const nodes = out ? payload[dcid].out || [] : payload[dcid].in || [];
for (const node of nodes) {
if (!uniqueResults.has(dcid)) {
uniqueResults.set(dcid, new Set());
}
if ("dcid" in node) {
uniqueResults.get(dcid).add(node.dcid);
} else if ("value" in node) {
uniqueResults.get(dcid).add(node.value);
}
}
}
// Make sure each dcid is in the results map, and convert all sets to arrays
const results = {};
for (const dcid of dcids) {
results[dcid] = Array.from(uniqueResults.get(dcid) || []);
}
return results;
}
async function getTriples(dcids, limit = MAX_LIMIT) {
// Filter out NaN values and generate the request payload
dcids = dcids.filter((v) => v === v);
const url = API_ROOT + API_ENDPOINTS.get_triples;
const payload = await sendRequest(url, { dcids, limit });
// Create a map from dcid to list of triples
const results = new Map();
for (const dcid of dcids) {
results.set(dcid, []);
for (const t of payload[dcid]) {
let triple;
if ("objectId" in t) {
triple = [t.subjectId, t.predicate, t.objectId];
} else if ("objectValue" in t) {
triple = [t.subjectId, t.predicate, t.objectValue];
}
results.get(dcid).push(triple);
}
}
return Object.fromEntries(results);
}
/* module.exports = {
getPropertyLabels,
getPropertyValues,
getTriples,
};*/
return {
_post,
_getDirection,
properties,
propertyValues,
getTriples,
getPropertyLabels,
getPropertyValues
};
}