Convert an object into a key value pair in JSON - node.js

I've been trying to render my API response from Nodejs to display on my react table. I want to perform some calculations and filter out a few things on the response from the API response. But later while trying to display it on my tables, I'm having complications. I know its a pretty simple task but I'm unable to come up with the proper logic or approach for this. Thank you for helping out.
.then(response => {
console.log(response);
const result = response.data.rows;
setRes(result)
var arr = [];
Object.keys(result).forEach(function(key) {
arr.push(result[key]);
});
const filtered = {
Greeters:
{
nvCount: 0,
Taken: 0,
vCount: 0
},
Cleaning:{
nvCount: 0,
Taken: 0,
vCount: 0,
},
Intercession:{
nvCount: 0,
Taken: 0,
vCount: 0,
},
Media:{
nvCount: 0,
Taken: 0,
vCount: 0,
},
KidsChurch:{
nvCount: 0,
Taken: 0,
vCount: 0,
},
};
arr.map((el, i) => {
if (el.team.includes('Greeters')) {
if (el.preference.includes('NON-VEG')) {
filtered.Greeters.nvCount++;
}
else if (el.preference.includes('VEG')) {
filtered.Greeters.vCount++;
}
if (el.taken===true ) {
filtered.Greeters.Taken++;
}
}
else if (el.team.includes('Cleaning')) {
if (el.preference.includes('NON-VEG')) {
filtered.Cleaning.nvCount++;
}
else if (el.preference.includes('VEG')) {
filtered.Cleaning.vCount++;
}
if (el.taken===true ) {
filtered.Cleaning.Taken++;
}
}
else if (el.team.includes('Intercession')) {
if (el.preference.includes('NON-VEG')) {
filtered.Intercession.nvCount++;
}
else if (el.preference.includes('VEG')) {
filtered.Intercession.vCount++;
}
if (el.taken===true ) {
filtered.Intercession.Taken++;
}
}
else if (el.team.includes('Media')) {
if (el.preference.includes('NON-VEG')) {
filtered.Media.nvCount++;
}
else if (el.preference.includes('VEG')) {
filtered.Media.vCount++;
}
if (el.taken===true ) {
filtered.Media.Taken++;
}
}
else if (el.team.includes('Kids Church')) {
if (el.preference.includes('NON-VEG')) {
filtered.KidsChurch.nvCount++;
}
else if (el.preference.includes('VEG')) {
filtered.KidsChurch.vCount++;
}
if (el.taken===true ) {
filtered.KidsChurch.Taken++;
}
}
});
The response data from the API:
0
:
{id: '56', name: 'Prajwal V', phone: '990*******', preference: 'NON-VEG', team: 'Greeters', taken: false}
1
:
{id: '57', name: 'Amulya', phone: '63605******', preference: 'NON-VEG', team: 'Greeters', taken: true}
2
:
{id: '58', name: 'Devika', phone: '8618******', preference: 'NON-VEG', team: 'Greeters', taken: false}
3
:
{id: '59', name: 'Guru', phone: '9019*****', preference: 'NON-VEG', team: 'Greeters', taken: true}
4
:
{id: '60', name: 'Peter', phone: '9988*****', preference: 'VEG', team: 'Cleaning', taken: false}
I just want to find out the count("NON-VEG"), count("VEG"), and count(taken) for each team.
And I want to display these based on a SELECT dropdown that chooses the Team. eg: Select: 'Greeters', the count("NON-VEG"), count("VEG"), and count(taken) for 'Greeters' must be displayed in tabular format.
Current attempt,
<Select
className='SelectTeam'
closeMenuOnSelect={true}
components={animatedComponents}
isMulti={false}
options={teams}
name='team'
onChange={handleSelect}
/>
{res.map(el => {
return(
<div>
{team == el.team &&
<tr key={el.team}>
<td>{el.name}</td>
<td>{el.preference}</td>
</tr>
}
</div>
)
})
}
The data in the 'filtered' object has all the necessary data needed. In other words, I just need to display that filtered data based on the team selected or tell me a better approach to handle this complication
Thank you so much for helping out.

You can construct the filtered object dynamically like below code
let filtered = {};
teams.map(team=>{
filtered[team.name] = {
nvCount: 0,
Taken: 0,
vCount: 0,
};
});
result.map(user => {
if (user.preference.includes("NON-VEG")) {
filtered[user.team].nvCount += 1;
} else if (user.preference.includes('VEG')) {
filtered[user.team].vCount += 1;
}
if (user.taken === true) {
filtered[user.team].Taken += 1;
}
});
console.log(filtered);
setFilteredData(filtered);
Your filtered object would look like this,
{
"Greeters": {
"nvCount": 4,
"Taken": 2,
"vCount": 0
},
"Cleaning": {
"nvCount": 0,
"Taken": 0,
"vCount": 1
}
}
store it in filteredData state and display it
{selectedTeam && (
<>
<div>NV count: {filteredData[selectedTeam].nvCount}</div>
<div>Veg count: {filteredData[selectedTeam].vCount}</div>
<div>Taken: {filteredData[selectedTeam].Taken}</div>
</>
)}
selectedTeam is the selected data from your select box.

Related

CouchDB display distinct values

I have a document like below,
{
"id": "7d9fdc2f4846544d62da3421bf011b31",
"al": [
{ "id16": "0x1d42",
"pos": {
"x": 10.32,
"y": 11.13,
"z": 1.22
},
"resultTime": "2020-06-01T20:45:34.976Z"
},
{ "id16": "0x1342",
"pos": {
"x": 0.32,
"y": 1.13,
"z": 13.22
},
"resultTime": "2021-06-01T20:45:34.976Z"
}
.
.
.
],
"Timestamp": 272179,
"Oid": "Onion1",
}
and Design document is like below
{
"id": "_design/GetALwithAnchorID",
"key": "_design/GetALwithAnchorID",
"value": {
"rev": "32-6db6c4e105336d47a6c8e7e8458ee345"
},
"doc": {
"_id": "_design/GetALwithAnchorID",
"_rev": "32-6db6c4e105336d47a6c8e7e8458ee345",
"views": {
"GetALwithAnchorID": {
"map": "function (doc) {\n\n for (var i=0; i<doc.al.length; i++) { \n emit(doc.al[i].id16, doc.al[i].pos);\n }\n \n}\n\n",
"reduce": "_approx_count_distinct"
}
},
"language": "javascript"
}
}
when I query the view like
http://127.0.0.1:5984/rtls/_design/GetALwithAnchorID/_view/GetALwithAnchorID?group_level=1&key=%220x1d42%22
I get the results as below
{"rows":[
{"key":"0x1d42","value":1}
]}
But I want distinct values of id16 and pos of id16. and to sort these distinct values by time and display the values of pos instead of "value":1 when Iquery?
thank you in advance.
OK so not quite the same as this similar answer. Anyone coming across this Q/A, I recommend reading over that answer.
Consider the following emit for your given doc structure:
doc.al.forEach(e => emit(
[e.pos.x, e.pos.y, e.pos.z, e.resultTime], // key
[e.id16, e.pos, e.resultTime]) // value
));
The emit's complex key visualized in the index (loosely not verbatim):
[-3,-2,-1,"2017-10-28T22:56:58.852Z"]
[-3,-2,-1,"2019-01-23T03:33:20.958Z"] **
. . .
[0,0,0,"2016-05-27T01:38:36.305Z"]
[0,0,0,"2016-12-27T05:17:02.255Z"] **
. . .
[1,2,3,"2016-11-14T17:31:59.468Z"]
[1,2,3,"2017-07-17T07:52:38.180Z"] **
Where each ** the last item in the pos group and significantly the most recent resultTime. All due to CouchDB's collation.
Working with CouchDB demands understanding the B-tree, and it's documentation has a great rundown of it in its Reduce/Rereduce documentation.
Now consider this reduce function:
function(keys,values,rereduce) {
return values[0];
}
It doesn't look terribly impressive, but further consider calling the view with these parameters:
{
reduce: true,
group_level: 1,
descending: true
}
By reversing the order of the index scan with descending the reduce function is guaranteed to return the most recent row with respect to resultTime of any given pos group.
Here's a simple demo using pouchDB. It generates 6 documents with random resultTime's and randomly selects pos from a pool of 3. Have a look at the design doc.
async function showReduceDocs(view) {
let result = await db.query(view, {
reduce: true,
group_level: 1,
descending: true
});
// show
debugger;
gel('view_reduce').innerText = result.rows.map(row => `${JSON.stringify(row.value)}`.split(',').join(', ')).join('\n');
return result;
}
async function showViewDocs(view) {
let result = await db.query(view, {
reduce: false,
include_docs: false
});
//show
gel('view_docs').innerText = result.rows.map(row => JSON.stringify(row.key))
.join('\n');
}
function getDocsToInstall(count) {
// design document
const ddoc = {
"_id": "_design/SO-66231293",
"views": {
"id16": {
"map": `function (doc) {
doc.al.forEach((e) => emit([e.pos.x, e.pos.y, e.pos.z, e.resultTime],[e.id16, e.pos, e.resultTime]));
}`,
"reduce": `function(keys,values,rereduce) {
return values[0];
}`
}
}
};
// create a set of random documents.
let docs = new Array(count);
let docId = 65;
const posSeed = [{
x: 0,
y: 0,
z: 0
},
{
x: 1,
y: 2,
z: 3
},
{
x: -3,
y: -2,
z: -1
}
];
const dateSeed = [new Date(2000, 0, 1), new Date(), 0, 24];
while (count--) {
let n = 6;
let doc = {
_id: String.fromCharCode(docId++),
al: new Array(n)
};
while (n-- > 0) {
doc.al[n] = {
"id16": "0x000" + n,
"pos": posSeed[Math.floor(Math.random() * 100) % 3],
"resultTime": randomDate(...dateSeed).toISOString()
};
}
docs[count] = doc;
}
docs.push(ddoc);
return docs;
}
const db = new PouchDB('SO-66231293', {
adapter: 'memory'
});
(async() => {
// install docs and show view in various forms.
await db.bulkDocs(getDocsToInstall(6));
gel('content').classList.remove('hide')
showReduceDocs('SO-66231293/id16');
showViewDocs('SO-66231293/id16');
})();
const gel = id => document.getElementById(id);
/*
https://stackoverflow.com/questions/31378526/generate-random-date-between-two-dates-and-times-in-javascript/31379050#31379050
*/
function randomDate(start, end, startHour, endHour) {
var date = new Date(+start + Math.random() * (end - start));
var hour = startHour + Math.random() * (endHour - startHour) | 0;
date.setHours(hour);
return date;
}
<script src="https://cdn.jsdelivr.net/npm/pouchdb#7.1.1/dist/pouchdb.min.js"></script>
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.memory.min.js"></script>
<div id='content' class='hide'>
<div>View: reduce</div>
<pre id='view_reduce'></pre>
<hr/>
<div>View: complex key</div>
<pre id='view_docs'></pre>
</div>
Edit
Amended the demo snippet according to OP's comments.

Update if value not undefined - mongoose

I want to update the value if key in the payload should have some value (not undefined or any false value). I don't want to check every value that makes code lengthy.
await Parent.findByIdAndUpdate(
payload.TID,
{
healthTests: payload.foo,
otherHealthtest: payload.bar,
},
{ new: true, fields: { updatedAt: 0, createdAt: 0, __v: 0 } },
);
You can use Object.entires() to iterate keys and values and build your updateObj:
let updateObj = {};
for(let [key, value] of Object.entries(payload)){
if(value !== undefined){
updateObj[key] = value;
}
}
await Parent.findByIdAndUpdate(
payload.TID, updateObj,
{ new: true, fields: { updatedAt: 0, createdAt: 0, __v: 0 } },
);
example:
let payload = { foo: 1, bar: undefined, baz: 3};
let updateObj = {};
for(let [key, value] of Object.entries(payload)){
if(value !== undefined){
updateObj[key] = value;
}
}
console.log(updateObj);

Setting a react state in callback does not work as expected

I am making barcode reading app. I use Quaggajs and Reactjs.
Quaggajs has a function Quagga.onDetected(callback), the callback has one parameter result. The result is containing the detected barcode. I am having a react state (const [count, setCount] = useState(0);) in which I am counting the detected barcodes. The problem is that when I use setCount(count + 1) in the callback the count variable is allways it's initial value (0) so every time onDetect the setCount is setting the new value to be 1.
Here is an example of the functional react component I use(I think that there is no problem getting the count and setCount from the props of ):
const Body = ({setCount, count, ...rest }) => {
const start = () => {
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
constraints: {
facingMode: "environment",
},
area: {
top: "30%",
bottom: "30%"
}
},
locate: false,
frequency: 50,
decoder: {
readers: [
// "code_128_reader",
"ean_reader",
// "ean_8_reader",
// "code_39_reader",
// "code_39_vin_reader",
// "codabar_reader",
// "upc_reader",
// "upc_e_reader",
// "i2of5_reader"
],
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
},
}, function (err) {
if (err) {
console.log(err);
return
}
console.log("Initialization finished. Ready to start");
Quagga.start();
});
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
Quagga.onDetected((result) => {
if (result && result.codeResult && result.codeResult.startInfo && result.codeResult.startInfo.error < 0.03) {
console.log("Sould change")
setCount(count + 1);
}
});
}
const stop = () => { Quagga.stop(); }
useEffect(() => {
start();
console.log("CHANGE BODY");
return () => {
stop();
}
}, [])
return (
<Grid container justify="center">
<div id="interactive" className="viewport" style={{ position: 'unset', width: '100vw', height: "100vh" }}>
<video src=""></video>
<canvas class="drawingBuffer"></canvas>
</div>
</Grid>
)
}

Elasticsearch js query with must and must_not

I am trying to get a query to run with both must and must_not, but have not had any luck with the syntax I am attempting. I see a lot of people on StackOverflow using quotes on both sides like they would be in a Curl call, but this is straight out of a node application.
I will show the query that does work, and I am simply trying to add what I do not want to be included in the outcome. In either case, because this is just trash data that is on a local dev environment, the outcome should match.
First the working query:
client.search({
index: config.ES_INDEX,
type: "issue",
body: {
query: {
match: {
issue_state: 'Closed'
}
},
size: 1000
}
}).then(function(resp){
console.log(util.inspect(resp, {showHidden: false, depth: null}));
}).catch(function(err){
console.log('Failed to search. ' + err.message);
});
Output:
{ took: 5,
timed_out: false,
_shards: { total: 5, successful: 5, failed: 0 },
hits:
{ total: 1,
max_score: 1,
hits:
[ { _index: 'noc_tool',
_type: 'issue',
_id: 'Sy2IQFMLe',
_score: 1,
_source:
{ job_name: 'Job Name 1',
is_maintenance: 'no',
servicenow_id: 'lkjjklh',
type: 'Chase',
start_time: '1970-01-01T23:15:00.000Z',
maint_reminder: null,
update_duration: '4 Hours',
location: 'Test Group',
issue_state: 'Closed',
notes: [ { created_on: 1484063571941, body: 'lkjlkjhlkj' } ],
emailService: { lastEmailAt: 1484237594114 },
created_on: 1484063571941,
updated_on: 1484240538801,
reason: 'because I want to' } } ] } }
Now, the failed query:
client.search({
index: config.ES_INDEX,
type: "issue",
body: {
query: {
bool: {
must: [
{
term: {
issue_state: 'Closed'
}
}
],
must_not: [
{
term: {
is_maintenance: 'yes'
}
}
]
}
},
size: 1000
}
}).then(function(resp){
console.log(util.inspect(resp, {showHidden: false, depth: null}));
}).catch(function(err){
console.log('Failed to search. ' + err.message);
});
Output:
{ took: 6,
timed_out: false,
_shards: { total: 5, successful: 5, failed: 0 },
hits: { total: 0, max_score: null, hits: [] } }
Any help here would be much appreciated.
I ended up using a little "reverse logic" but here is what is working..
return new Promise(function(resolve, reject) {
client.search({
index: config.ES_INDEX,
type: "issue",
body: {
query: {
bool: {
must:[
{
match: {
issue_state: 'Closed'
}
},
{
match: {
is_maintenance: 'no'
}
}
]
}
},
size: 1000
}
}).then(function (resp) {
resolve (resp.hits.hits);
}).catch(function (err) {
reject('Failed to search. ' + err.message);
});

How to scan through objects that are inside object. [JavaScript]

I am making a barcode scanner for my school project but i am stuck. I dont know how to scan through this object. I have this object with objects inside, and I need to scan through each object inside storage variable to check its barcode.
var storage = {
bolts: {
barcode: 57263144,
price: 0.5,
name: 'Plain Brackets',
stock: 25,
},
brackets: {
barcode: 13245627,
price: 0.2,
name: '100mm Bolts',
stock: 2,
},
}
I have a variable called barcode, and I need to test this variable if its the same like one of these. I tried using
for (var key in storage){
if (storage[key].barcode === barcode){
}
}
I would like the most simple way to do that.
Use Object.keys:
Object.keys(obj).forEach(function(key) {
console.log(key, obj[key]);
});
Below is the example:
var storage = {
"bolts": {
barcode: 57263144,
price: 0.5,
name: 'Plain Brackets',
stock: 25,
},
"brackets": {
barcode: 13245627,
price: 0.2,
name: '100mm Bolts',
stock: 2,
}
}
var barcode = 57263144;
Object.keys(storage).forEach(function(key) {
if(storage[key].barcode === barcode) { console.log("do something")}
});
A Fiddle:
https://jsfiddle.net/spechackers/34bhthza/
Use the recursive function to verify if exist more nodes in the objects, example:
const complexObj = {
name: "nobody",
address: { number: 22, moreNumbers: [1,2,3,4,5] },
colors: ["green", "red"],
numbersAgain: { first: 1, second: 4 }
};
function scanObj(obj){
for (let i in obj) {
/*
*Do some verificatio, example:
*I'd like to verify all numbers and if the numbers is greater than 3:
*/
if(typeof obj[i] == "number" && obj[i] > 3){ console.log(obj[i]); }
if (typeof obj[i] === "object") {
scanObj(obj[i])
}
}
}
//call the method
scanObj(complexObj);
Output: 22 4 5 4

Resources