Return specific fields in cloudant - node.js

I'm making a .list() call on cloudantDB using node.JS and I have the following return
"success": true,
"data": {
"status": true,
"res": {
"total_rows": 1,
"offset": 0,
"rows": [
{
"id": "012022",
"key": "012022",
"value": {
"rev": "1-0d48e71b8a774b394c2b6f380e600cde"
},
"doc": {
"_id": "012022",
"_rev": "1-0d48e71b8a774b394c2b6f380e600cde",
"year": 2022,
"month": "01",
"count": 0
}
}]
}
}
I'm making the call this way
CloudantConnection.use("history_metric")
.list({
include_docs: true,
limit: 12,
})
.then((res) => {
response = { status: true, res };
})
.catch((error) => {
response = { status: false, error };
});
I would like to know if there is any way to not return the _id and _rev in the DOC, I wanted a return like this
"success": true,
"data": {
"status": true,
"res": {
"total_rows": 1,
"offset": 0,
"rows": [
{
"id": "012022",
"key": "012022",
"value": {
"rev": "1-0d48e71b8a774b394c2b6f380e600cde"
},
"doc": {
"year": 2022,
"month": "01",
"count": 0
}
}]
}
}

The list() call maps to the Cloudant api endpoint _all_docs and so is beholden to returning what it returns, which includes both the id and rev id for each returned row. This is typically what you want: if you do any subsequent processing on the documents returned, you'd need to refer to these ids.
If you want to discard these, for example, if sending the data onwards to something else that doesn't expect them, you need to filter them out yourself on your side.

Related

How to delete documents from two collections in mongodb

As of now I am able to delete the specific files from filestorage.files collection based on query but I am trying to delete the specific chunks from filesstorage.chunks collection based on files_id. Can someone please suggest me the good approach to achieve it.
Should I use aggregations ? or any looping mechanism ?
Please find the below details
filestorage.files collection:
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "pexels-lucie-liz-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/pexels-lucie-liz-3165335_2022-10-27T11-16-58.jpg"
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd4"
},
"length": 878669,
"chunkSize": 261120,
"uploadDate": {
"$date": {
"$numberLong": "1666869418612"
}
},
"filename": "nature-3165335_2022-10-27T11-16-58.jpg",
"contentType": "image/jpeg",
"metadata": {
"originalname": "nature-3165335.jpg",
"parentFolder": {
"$oid": "636cd238692344da47f3e301"
},
"path": "files/Folder1/Folder3/nature-3165335_2022-10-27T11-16-58.jpg"
}
}]
filestorage.chunks collection :
[{
"_id": {
"$oid": "635a68aa0651c2d869fc3fe6"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "xyz"
"subType": "00"
}
}
},
{
"_id": {
"$oid": "635a68aa0651c2d869fc3fd5"
},
"files_id": {
"$oid": "635a68aa0651c2d869fc3fd3"
},
"n": 0,
"data": {
"$binary": {
"base64" : "abcd"
"subType": "00"
}
}
}]
Here is what I have tried :
delete_folder_files: async (ctx:any) => {
// here I am able to delete all the files but confused how to connect chunks schema and delete chunks // based on files_id.
await FileStorage.deleteMany({'metadata.parentFolder': ctx.params.id});
await FileChunk.deleteMany({files_id : ? })
ctx.status = HttpStatusCode.OK;
}
As I can see you are deleting the file ids . So after that you do not have any relation to delete the chunks in fileChunk collection .
Here is what I am thinking , First get all the file ids as an array and later you can delete the chunks with the folder_ids by querying them as array.
const file_ids = await FileStorage.find({'metadata.parentFolder': ctx.params.id },{_id:1}).distinct('_id');
await FileStorage.deleteMany({'metadata.parentFolder':ctx.params.id });
await FileChunk.deleteMany({files_id:{$in:file_ids}});
Note : Please check the performance of the query by uploading multiple files.

Get aggregate with lookup in single Object

my problem is how I get a simple object of ownerDetails, correct me if my code is wrong
data I got, from my code
{
"status": true,
"data": [
{
"_id": "61a2a9680b122bc154cbd6af",
"ownerName": "Ajay",
"mobile": 878787878,
"designation": "IT",
"gender": "Male",
"age": 26,
"carDetails": [
{
"carName": "BUY",
"color": "blue",
"sheets": 8,
"avgSpeed": 105,
"price": 850000,
"model": "C110"
},
{
"carName": "GTR",
"color": "blue",
"sheets": 4,
"avgSpeed": 105,
"price": 98000,
"model": "G120"
}
]
}
]
}
i want data like this,
{
"status": true,
"ownerDetails": {
"_id": "61a2a9680b122bc154cbd6af",
"ownerName": "Ajay",
"mobile": 878787878,
"designation": "IT",
"gender": "Male",
"age": 26,
"total_car": 2,
}
}
code for getting data from collections
exports.getOwnerDetails = async (req, res, next) => {
try {
Owner.aggregate([
{
$match: { ownerName: req.body.ownerName }
},
{
$lookup: {
from: "cars",
localField: "ownerName",
foreignField: "ownerName",
as: "carDetails",
},
},
{
$project: {
"carDetails._id": 0,
"carDetails.ownerName": 0,
},
},
]).then((data) => {
res.json({
status: true,
data: data,
});
});
} catch (error) {
res.status(500).json({
status: false,
msg: "Error : " + error,
});
}
};
in may returning data, I got an array of carDetails, but I only need that how many are owned by an Owner, and return a simple object of ownerDetails
$lookup return an array because more than one values can match the join. If you want to get only one value you can get the first element from the array. Then you can add these aggregation stages:
First $addFields to get the first element from the array (index 0).
Then use $project to get the desired output.
{
"$addFields": {
"data": {
"$arrayElemAt": ["$data",0]
}
}
},
{
"$project": {
"status": 1,
"ownerDetails": {
"_id": "$data._id",
"ownerName": "$data.ownerName",
"mobile": "$data.mobile",
"designation": "$data.designation",
"gender": "$data.gender",
"age": "$data.age",
"total_car": {
"$size": "$data.carDetails"
}
}
}
}
Example here
Query
i am not sure if this is what you want
unwind all owners from data
and from each owner, count its cars number
Test code here
aggregate(
[{"$unwind": {"path": "$data"}},
{"$set":
{"data.total_car": {"$size": "$data.carDetails"},
"data.carDetails": "$$REMOVE",
"_id": "$$REMOVE"}},
{"$set": {"ownerDetails": "$data", "data": "$$REMOVE"}}])

how to filter the data returned in find FeatherJs

I have this code that returns this result:
// Use this hook to manipulate incoming or outgoing data.
// For more information on hooks, see: http://docs.feathersjs.com/api/hooks.html
module.exports = function (options = {}) { // eslint-disable-line no-unused-vars
return async context => {
// Get `app`, `method`, `params` and `result` from the hook context
const { app, method, result, params } = context;
// Make sure that we always have a list of users either by wrapping
// a single message into an array or by getting the `data` from the `find` method's result
const interacts = method === 'find' ? result.data : [ result ];
// console.log(users);
// Asynchronously get user object from each message's `userId`
// and add it to the message
await Promise.all(interacts.map(async interact => {
// await Promise.all(user.map(async interacts => {
// Also pass the original `params` to the service call
// so that it has the same information available (e.g. who is requesting it)
// bots.botId = await app.service('bots').get(bots.botId, params);
interact.display = await app.service('messages').find({
query: {
to: "ijHTUNeSbSQNICOC",
from: "8Tp5maaTePqiD3DI",
$limit: 1,
$sort: {
createdAt: -1
}
}
});
// }));
}));
console.log(context);
// Best practice: hooks should always return the context
return context;
};
};
return this result:
"total": 6,
"limit": 10,
"skip": 0,
"data": [
{
"userId": "8Tp5maaTePqiD3DI",
"interactUser": "ijHTUNeSbSQNICOC",
"_id": "3r3MY8SagJMqcEj4",
"display": {
"total": 2,
"limit": 1,
"skip": 0,
"data": [
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
]
}
},
{
"userId": "fNEgNVk6yh3msVa8",
"interactUser": "Z5DO1Gx2YpXLTRBb",
"_id": "KAtOheLC6AEiJL41",
"display": {
"total": 2,
"limit": 1,
"skip": 0,
"data": [
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
]
}
},
{
"userId": "Z5DO1Gx2YpXLTRBb",
"interactUser": "Z5DO1Gx2YpXLTRBb",
"_id": "LgoqQxxR8538fnu3",
"display": {
"total": 2,
"limit": 1,
"skip": 0,
"data": [
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
]
}
},
{
"userId": "8Tp5maaTePqiD3DI",
"interactUser": "8Tp5maaTePqiD3DI",
"_id": "PuUaonKg3hol2wz0",
"display": {
"total": 2,
"limit": 1,
"skip": 0,
"data": [
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
]
}
},
how to leave only data this..:
"userId": "Z5DO1Gx2YpXLTRBb",
"interactUser": "fNEgNVk6yh3msVa8",
"_id": "T3ekz58yNDacS5o2",
"display":
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
"userId": "Z5DO1Gx2YpXLTRBb",
"interactUser": "fNEgNVk6yh3msVa8",
"_id": "T3ekz58yNDacS5o2",
"display":
{
"text": "nome1",
"from": "8Tp5maaTePqiD3DI",
"to": "ijHTUNeSbSQNICOC",
"createdAt": 1554757301176,
"_id": "o2vkUj7suYzhEZk7"
}
If there is any way, or rather to format the results returned by the query
The reason why you have those results is because of pagination. Disabling the pagination will only return the data.
You can create your own hook to handle queries that will disable the pagination if requested.
The good news is, there is a package that will solve your problem, feahters-hooks-common.
The exact hook you want is documented in (disablepagination) .

Unwind inside lookup in Mongoose

I have 2 entities to merge: Customer and Feedback. Feedback contains an embedded array of upvotes (Upvote)
A customer is not able to upvote more than once for a specific feedback.
What I would like to achieve is - given a specific feedback id - get the complete list of customers with an additional virtual attribute that states whether he/she upvoted the given feedback.
Customer.aggregate(
[
{
$match: { company_id: new ObjectID(req.user.company_id) }
},
{
$lookup: {
from: 'feedbacks',
let: { 'c_id': '$_id' },
pipeline: [
{
$unwind: '$upvotes'
},
{
$match: { $expr: { $eq: ['$upvotes.customer_id._id', '$$c_id'] } }
}
],
as: 'upvotes'
}
}
],
function(err, customers) {
if (err) {
console.log(err);
res.status(400).send(err);
} else {
res.send({ customers });
}
}
);
To do that I have to look through the list of upvotes for that specific feedback and, then, join it with the customer table using the customer_id.
The above mentioned approach does not work. Any suggestion what I am doing wrong?
Sample data (Feedback)
{
"size": 0,
"points": 50,
"status": "open",
"potential": 0,
"real": 5000,
"_id": "5c3d033271ceb7edc37d156c",
"title": "Custom Invoice Templates",
"description": "Provide an editor to create custom invoices.",
"owner_id": {
"_id": "5c3b684f7cec8be977c2a465",
"email": "maurizio#acme.com"
},
"company_id": "5c3b684f7cec8be977c2a462",
"project_id": "5c3b68507cec8be977c2a468",
"upvotes": [
{
"_id": "5c3fa5b371ceb7edc37d159a",
"comments": "bbbb",
"priority": "should",
"customer_id": {
"size": 0,
"potential": 0,
"real": 5000,
"_id": "5c3b68507cec8be977c2a485",
"name": "Oyomia Ltd."
},
"owner_id": {
"_id": "5c3b684f7cec8be977c2a465",
"email": "maurizio#acme.com"
}
}
],
"updatedAt": "2019-01-16T21:44:19.215Z",
"createdAt": "2019-01-14T21:46:26.286Z",
"__v": 0
}
Sample data (Customer)
{
"size": 0,
"potential": 0,
"real": 5000,
"_id": "5c3b68507cec8be977c2a485",
"name": "Oyomia Ltd.",
"contact": {
"_id": "5c40f8de71ceb7edc37d15ab",
"name": "Nick Page",
"email": "np#oyoma.com"
},
"company_id": "5c3b684f7cec8be977c2a462",
"deals": [
{
"value": 5000,
"_id": "5c3b68507cec8be977c2a487",
"name": "Armour batch",
"status": "won",
"type": "non_recurring",
"updatedAt": "2019-01-13T16:33:20.870Z"
}
],
"__v": 0,
"updatedAt": "2019-01-17T21:51:26.877Z"
}

Node.js + Firebase orderByChild not working

I am trying to figure out this nested ordering and nothing I do will work.
Here is a sample of the data structure I am trying to order:
{
"-KV_Lrm_93Agm8kAuXql": {
"body": {
"Acceleration": "0.0",
"Altitude": "11",
"Battery": "12.7",
"Date": "2016/09/10",
"order": 1,
"time": "2016-10-19T20:26:32Z"
}
},
"-KV_LuTfJ9VrKRHoRWuw": {
"body": {
"Acceleration": "0.0",
"Altitude": "11",
"Battery": "12.7",
"Date": "2016/09/10",
"order": 5,
"time": "2016-10-21T20:26:32Z"
}
},
"-KV_Lx9VABuEB8D3I-i1": {
"body": {
"Acceleration": "0.0",
"Altitude": "11",
"Battery": "12.7",
"Date": "2016/09/10",
"order": 2,
"time": "2016-10-01T20:26:32Z"
}
},
"-KV_LzQOM3rHEKQuwyHQ": {
"body": {
"Acceleration": "0.0",
"Altitude": "11",
"Battery": "12.7",
"Date": "2016/09/10",
"order": 10,
"time": "2016-09-01T20:26:32Z"
}
},
"-KV_M0fdznAbKanHoY91": {
"body": {
"Acceleration": "0.0",
"Altitude": "11",
"Battery": "12.7",
"Date": "2016/09/10",
"order": 6,
"time": "2016-09-20T20:26:32Z"
}
}
}
Per the firebase documentation (https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html) you can do a "deep path query". In my case, if I want to sort by order I should be able to do:
.orderByChild("body/order")
But this does nothing. It has no effect on the ordering of the results. I have tried ordering on Date and time as well and neither work. Here is my full node function. This returns the results, just not ordered:
app.get('/api/xirgo-data', function(req, res)
{
var ref = db.ref("xirgo");
ref
.orderByChild("body/order")
.on("value", function(snap) {
return res.json(snap.val());
});
});
Thanks!
When you request the value of a query in Firebase, the resulting snapshot contains the keys, values and ordering information for the matching children.
But when you then convert this to a dictionary/associative array/JavaScript object, the ordering information is lost since JavaScript objects are inherently unordered.
To ensure you can access the matching items in the correct order, use the built-in DataSnapshot.forEach() method:
var ref = db.ref("xirgo");
ref
.orderByChild("body/order")
.on("value", function(snapshot) {
snapshot.forEach(function(child) {
console.log(child.key+': '+child.val());
});
});

Resources