i am trying to find corder data in below documents but i can not do this work if you know about how to find nested array data in below document so please find data for {corder}.
{
"_id": "63064232cf92b07e37090e0a",
"sname": "Bombay collection ",
"phone": 9963366555,
"costomer": [
{
"cname": "Ammar ",
"cphone": 919628497,
"ccity": "Palanpur",
"_id": "632ef012a9b88eb59d0210fa",
"corder": [
{
"clothType": "Pathani",
"prize": 236,
"date": "2022-09-24",
"status": "true",
"_id": "632ef078a9b88eb59d02110c"
}
],
}
],
},
and my code is id = "main document id" & obid ="cosomer id " & orid = " order id "
app.get('/getuser/:id/:obid/:orid', async (req, res) => {
try {
const id = req.params.id
const obid = req.params.obid
const orid = req.params.orid
console.log(id);
const peruserdata = await getschema.find({ 'costomer.corder': orid } ,
{ "_id": orid, "costomer.$.corder": { $elemMatch: { "_id": orid } } });
res.status(201).json(peruserdata);
} catch (error) {
console.log(error);
res.send(error)
}
})
I'm trying to retrieve documents matching an id through a simple SQL query in my JavaScript stored procedure. But it always returns that no document matches the id found. Tried all the things available in the Microsoft Documentation and the other StackOverflow answers. Here is my function:
function updateDocument () {
let context = getContext();
let collection = context.getCollection();
let collectionLink = collection.getSelfLink();
let response = context.getResponse();
tryQueryAndUpdate();
function tryQueryAndUpdate () {
var filterQuery = 'select * from user r WHERE r.id = "f5eddf33-7826-40c3-a634-9c349e5c7f73"';
let isAccepted = collection.queryDocuments(collectionLink, filterQuery, {}, function (err, documents, responseOptions) {
if (err) throw err;
if (documents.length > 0) {
console.log("Documents exists - " + documents.length);
} else {
// Else a document with the given id does not exist..
console.log("Document doesn't exist " + documents.length);
}
});
}
}
My document:
{
"firstName": "firstname",
"lastName": "lastname",
"email": "firstname.lastname#gmail.com",
"businessRole": "",
"functionalArea": null,
"type": "internal",
"status": "enable",
"modifiedDate": "2020-07-10T14:34:54.557Z",
"id": "f5eddf33-7826-40c3-a634-9c349e5c7f73",
"_rid": "H+pKAKZdGd0BAAAAAAAAAA==",
"_self": "dbs/H+pKAA==/colls/H+pKAKZdGd0=/docs/H+pKAKZdGd0BAAAAAAAAAA==/",
"_etag": "\"730103dd-0000-0100-0000-5f6302800000\"",
"_attachments": "attachments/",
"securityGroup": "c5d3dc10-bfa0-11ea-8394-48463089baf6",
"engagementId": "945acacf-a3ea-43ef-8e31-70576055ba4f",
"sort": {
"firstName": "firstname",
"lastName": "lastname"
},
"userStatus": "active",
"_ts": 1600324224
}
document:
container:
Any help would be appreciated. Thank you.
Execution parameters:
Console output:
I am trying to iterate (with a for..in loop) multiple entries and output them as a json object. Where I am running into difficulty is that the data only outputs a single list entry, and not all of them. Using AxiosJS in Node, I've found it outputs in the exact format I'd like. I'm unsure how to format my loop in order to output like this:
{
"Cardio_ETC": {
"name": "John",
"shift": "7a-7a",
"service": "ETC Cardiology",
"Office": "1234",
"cell": ""
},
"Cardio_STEMI": {
"name": "Pran",
"shift": "7a-7a",
"service": "STEMI Cardiology",
"Office": "34561321",
"cell": ""
},
"fastTrack1": {
"name": "Bob",
"shift": "7a-7p",
"service": "Fasttrack",
"Office": "X533 tel",
"cell": "X533"
},...etc
Here is my current code:
.then((data)=>{
connection.query("SELECT * FROM amion_onCall", function (err, result, fields){
//format results here
var fixed = new Object();
let i;
for (i in result){
aName = result[i].name;
serv = result[i].specialty;
aServ = serv.replace(' ','_');
aShift = result[i].shift;
aOff = result[i].office;
aCell = result[i].cell;
aTag = result[i].tag;
var data = {name:aName, service: aServ, shift: aShift, office: aOff, cell: aCell, tag: aTag};
Object.assign(fixed, data);
console.log(fixed);
What is the best way to format this for..in loop in order to output the above json?
In your case, If you want to use for in you can do this
const obj = {};
for (i in result) {
obj[result[i].tag] = {
name: result[i].name,
service: result[i].specialty.replace(' ', '_'),
shift: result[i].shift,
office: result[i].office,
cell: result[i].cell,
}
}
console.log(obj) // will have your answer
but I recommend using reduce
.then((data) => {
connection.query("SELECT * FROM amion_onCall",
function (err, result) {
const obj = result.reduce((o, item) => {
o[item.tag] = {
name: item.name,
service: item.specialty.replace(' ', '_'),
shift: item.shift,
office: item.office,
cell: item.cell,
}
return o
}, {});
console.log(obj)
})
})
Got an object containing a user id for each user and prices, would like to create a new object/array for each user (no duplicates) and be able to calculate the total sum of price for each user. Tried using Object.values() with map and filter but can't get it to work properly
{
"data": {
"item1": {
"price": "20",
"user": "user1"
},
"item2": {
"price": "10",
"user": "user2"
},
"item3": {
"price": "50",
"user": "user1"
}
}
}
Output something like this:
{
"users": {
"user1": {
"totalSum": "70",
},
"user2": {
"totalSum": "10",
}
}
}
I'm thinking about using map to present the "users"-data, maybe an array would be better?
Using function reduce.
Important: The attribute price is a String, this approach uses object Number to convert that value to a numeric one.
var obj = { "data": { "item1": { "price": "20", "user": "user1" }, "item2": { "price": "10", "user": "user2" }, "item3": { "price": "50", "user": "user1" } }};
var result = Object.keys(obj.data).reduce((a, k) => {
if (a.users[obj.data[k].user]) {
a.users[obj.data[k].user].totalSum += Number(obj.data[k].price);
} else {
a.users[obj.data[k].user] = {
"totalSum": Number(obj.data[k].price)
}
}
return a;
}, {
'users': {}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important; top: 0;
}
You could leverage ```reduce, more information here
code (haven't tried this)
var data = JSON.parse(mainObj).data;
var usersWithTotalExpenditure = Object.keys(data).reduce(function(result, key) {
var currentItem = data[key];
var useName = currentItem.user;
var price = Number(currentItem.price);
if (userName in result) {
result[userName].totalSum += price;
} else {
result[userName] = {
totalSum: price
};
}
return result;
}, {});
var resultObject = {
users: usersWithTotalExpenditure
}
You can use a forEach loop. This relies on Javascripts powerful OR operator, which coerces the first half of the expression to false if the current user's price is not defined (meaning it is a user the loop hasn't encountered before)
`c is your initial object's data, output is empty object`
const c = obj.data;
var output = {};
Object.keys(c).forEach((val) => {
output[c[val]["user"]] = parseInt(output[c[val]["user"]]) + parseInt(c[val]["price"]) || parseInt(c[val]["price"]);
})
I have the following data set:
{company:"One", employee:"John"},
{company:"One", employee:"Mike"},
{company:"One", employee:"Donald"},
{company:"One", employee:"Mickey"},
{company:"Two", employee:"Johnny"},
{company:"Two", employee:"David"},
Ideally, I want a query that returns all distinct companies, number of employees for each company, random employee for each company
{Company: "One" , employee_count=4, randomemployee="Donald"},
{Company: "Two" , employee_count=2, randomemployee="David"},
I do find a way to get company and employee_count using aggregate/group
However I don't find a way to add the randomemployee with the same query.
My aggregation:
function aggr (collection,cb){
collection.aggregate(([{$group:{_id:'$company',total:{$sum:1}}},{$sort:{total:-1}}]),function(err, l1){
cb(null, l1)
})
}
I began an other Sample function:
function onesample (collection,arg,cb){
collection.aggregate(([{ $match: { "company": arg }},{ $sample: { size: 1 }}]),function(err, item){
cb(null, item[0].employee)
})
}
But i'm loosing myself with callbacks and loop.
Any elegant way to do this within one query?
Thanks a lot.
following your answer, I tried the following code.
I have an issue with the callback of async.foreachof, seems it doesn't finish before leaving to next step: any clue?
var async = require("async");
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://localhost:27017/eyc0';
async.waterfall ([
function(cb) {
MongoClient.connect(url, function(err, db) {
cb(null,db)
})
},
function (db, cb) {
db.collection('kodes', function(err, coll) {
cb(null,db,coll)
})
},
function (db,coll, cb) {
var pipeline = [
{"$group": {"_id": "$ouat","total": { "$sum": 1}}},
{"$sort":{"total":-1} },
{"$project":{"_id": 0,"total":1,"company": "$_id"}}];
coll.aggregate(pipeline).toArray(function(err, dlist){
cb(null,db,coll,dlist)
})
},
function (db,coll,dlist, cb) {
// console.log(dlist)
cb(null,db,coll,dlist)
},
function (db,coll,dlist, cb) {
var dlist2 = []
async.forEachOf(
dlist,
function(item, key, cb){
var pipeline = [{ "$match": { "ouat": item.company } },{ "$sample": { size: 1 } }];
coll.aggregate(pipeline, function (err, data) {
item["randref"] = data[0].code;
console.log(item.company)
dlist2.push(item)
cb()
});
}
);
cb(null,db,coll,dlist,dlist2);
},
function (db,coll,dlist,dlist2, cb) {
console.log(dlist2)
console.log(dlist)
},
])
There's one approach that involves one query, it could be close but not as performant (as it uses $unwind) and won't give you the desired result (only the filtered company):
var pipeline = [
{
"$group": {
"_id": "$company",
"total": { "$sum": 1 },
"employees": { "$push": "$employee" }
}
},
{
"$project": {
"_id": 0,
"company": "$_id",
"employee_count": "$total"
"randomemployee": "$employees"
}
},
{ "$unwind": "$randomemployee" },
{ "$match": { "company": arg } },
{ "$sample": { size: 1 } }
];
collection.aggregate(pipeline, function(err, result){
console.log(result);
});
However, for a solution that uses callbacks from multiple queries, this can be handled easily with use of async module.
To get all distinct companies, number of employees for each company, random employee for each company consider using the async.waterfall() function where the first task returns the aggregation results with all distinct companies and number of employees for each company.
The second task uses the results from taks 1 above to iterate over using async.forEachOf(). This allows you to perform an asynchronous task for each item, and when they're all done do something else. With each document from the array, run the aggregation operation that uses the $sample operator to get a random document with the specified company. With each result, create an extra field with the random employee and push that to an array with the final results that you can access at the end of each task.
Below shows this approach:
var async = require("async");
async.waterfall([
// Load full aggregation results (won't be called before task 1's "task callback" has been called)
function(callback) {
var pipeline = [
{
"$group": {
"_id": "$company",
"total": { "$sum": 1 }
}
},
{
"$project": {
"_id": 0,
"company": "$_id",
"employee_count": "total"
}
}
];
collection.aggregate(pipeline, function(err, results){
if (err) return callback(err);
callback(results);
});
},
// Load random employee for each of the aggregated results in task 1
function(results, callback) {
var docs = []
async.forEachOf(
results,
function(value, key, callback) {
var pipeline = [
{ "$match": { "company": value.company } },
{ "$sample": { size: 1 } }
];
collection.aggregate(pipeline, function (err, data) {
if (err) return callback(err);
value["randomemployee"] = data[0].employee;
docs.push(value);
callback();
});
},
function(err)
callback(null, docs);
}
);
},
], function(err, result) {
if (err) return next(err);
console.log(JSON.stringify(result, null, 4));
}
);
With the the async.series() function, this is useful if you need to execute a set of async functions in a certain order.
Consider the following approach if you wish to get the all the distinct companies and their employee count as one result and the other random employee as another:
var async = require("async"),
locals = {},
company = "One";
async.series([
// Load random company
function(callback) {
var pipeline = [
{ "$match": { "company": company } },
{ "$sample": { size: 1 } }
];
collection.aggregate(pipeline, function(err, result){
if (err) return callback(err);
locals.randomcompany = result[0];
callback();
});
},
// Load full aggregation results (won't be called before task 1's "task callback" has been called)
function(callback) {
var pipeline = [
{
"$group": {
"_id": "$company",
"total": { "$sum": 1 }
}
},
{
"$project": {
"_id": 0,
"company": "$_id",
"employee_count": "total"
}
}
];
collection.aggregate(pipeline, function(err, result){
if (err) return callback(err);
locals.aggregation = result;
callback();
});
}
], function(err) { //This function gets called after the two tasks have called their "task callbacks"
if (err) return next(err);
//Here locals will be populated with 'randomcompany' and 'aggregation'
console.log(JSON.stringify(locals, null, 4));
}
);
db.comp.aggregate([
{$group:{_id:'$company',emp:{$addToSet:'$employee'}}},
{$project:{emp:1,employee_count:{'$size':'$emp'},
randomvalue:{'$literal':Math.random()}}},
{$project:{emp:1,employee_count:1,
randomposition:{'$floor':
{'$multiply':['$randomvalue', '$employee_count']}}}},
{$project:{'Company':'$_id', _id:0, employee_count:1,
randomemployee:{'$arrayElemAt':['$emp','$randomposition']}}},
{$sort:{Company:1}} ])
Seems to work!
A couple of results:
{ "employee_count" : 4, "Company" : "One", "randomemployee" : "Mike" }
{ "employee_count" : 2, "Company" : "Two", "randomemployee" : "Johnny" }
{ "employee_count" : 4, "Company" : "One", "randomemployee" : "Mickey" }
{ "employee_count" : 2, "Company" : "Two", "randomemployee" : "David" }