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());
});
});
Related
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.
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.
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"}}])
I have been asked in an interview to mutate the array of objects in such a way that the data appears in the following manner
[
{
"companyName": "ABC",
"members": [
{
"id": 13121212,
"firstName": "Ray",
"lastName": "Fernandis",
"points": 1800,
"position": 1
},
{
"id": 13131313,
"firstName": "Carrie",
"lastName": "Yoda",
"points": 1200,
"position": 2
}
]
}]
and the sample data was given below.
[
{
"communityName": "ABC",
"lastUpdateTimestamp": {
"date": {
"year": 2020,
"month": 10,
"day": 7
},
"time": {
"hour": 18,
"minute": 6,
"second": 5,
"nano": 536529000
}
},
"data": {
"listChannelsData": [
{
"channelId": 1234,
"channelName": "BCD",
"members": [
{
"id": 13121212,
"firstName": "Ray",
"lastName": "Fernandis",
"points": 1800,
"position": 1
}
]
}
]
}
},
{
"communityName": "DEF",
"lastUpdateTimestamp": {
"date": {
"year": 2020,
"month": 10,
"day": 7
},
"time": {
"hour": 18,
"minute": 6,
"second": 21,
"nano": 47894000
}
},
"data": {
"listChannelsData": [
{
"channelId": 3421,
"channelName": "GHI",
"members": [
{
"id": 13121212,
"firstName": "Nicholas",
"lastName": "Xin",
"points": 800,
"position": 2
},
{
"id": 13131313,
"firstName": "Carrie",
"lastName": "Yoda",
"points": 1000,
"position": 1
}
]
}
]
}
}
]
The agenda for me was to print the derived json from sample json and I could only figure out this much code which was a courtesy of stackoverflow
function dictionary(data) {
var map = {};
data.forEach(item => {
if (!Array.isArray(map[item.companyName])) {
map[item.companyName] = [item.data.listChannelsData];
} else {
map[item.communityName].push(item.data.listChannelsData);
}
});
return map;
}
console.log(dictionary(data));
But now when I try to pick up the data for the member using another foreach loop, I'm not able to access the data for members. Can anyone help me with the part where I can successfully access the member array and print the company name along side it
Try this code
var newArray = []
data.map((item, index) => {
newArray[index] = {companyName : item.communityName}
newArray[index].members = item.data.listChannelsData[0].members
})
data is the given data.
I'm a newbie when it comes to CouchDB. I come from a .NET SQL Server world.
In skimming through CouchDB the Definitive Guide I was like "wut wut this is awesome". Now I'm testing some of the things I learned in hopes of implementing it in the real world.
I just signed up for a Cloudant account a couple of weeks ago and started using it for some testing/learning.
In messing with linked documents, the whole theory behind looks simple and also the strait forward examples on the internet. Where I want to retrieve some information from a document that has an array of different linked documents, whom themselves have arrays of linked documents. Like a multi SQL Server that joins to many to many relationship tables. You'll see the code bellow. Hopefully it makes sense.
Take for example this SQL Query. Assuming that there is only one entry in each of the tables we should get one record back with all of the details for a shoe with a given sku. But if we had multiple shoe sizes we would have to write some more code.
select ci.sku
,sc.color
,ss.size
,si.url
from CatalogItem ci
join ShoeImages si
on ci.sku = si.sku
and ci.sku = '656F-PINSEC12'
join ShoeSizes ss
on ci.sku = ss.sku
join ShoeColors sc
on ci.sku = sc.sku
I would like CouchDB to return the following JSON by SKU at https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22
{
"_id": "689fe6982f4d604541db67ee4050a535",
"_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
"type": "catalogue-item",
"sku": "656F-PINSEC12",
"upc": "8549875231",
"shoe-colors":
[
{
"color": "black/houndstooth"
"shoe-sizes":
[
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
],
"shoe-images":
[
{
"full-images":
[
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images":
[
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
]
}
]
}
Given the following documents and map/reduce:
//--catalog item
{
"_id": "689fe6982f4d604541db67ee4050a535",
"_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
"type": "catalogue-item",
"sku": "656F-PINSEC12",
"upc": "8549875231",
"shoe-colors": [
{
"_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
"shoe-images": [
{
"_id": "7b547bae4ac911c6f05b97eba6cb355a"
}
],
"shoe-sizes": [
{
"_id": "12b6289d558d7ceb5bef725091666ce5"
}
]
}
]
}
//--shoe images
{
"_id": "7b547bae4ac911c6f05b97eba6cb355a",
"_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
"type": "shoe-images",
"sku": "656F-PINSEC12",
"color": "Black/Houndstoot",
"full-images": [
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images": [
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
//--shoe color
{
"_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
"_rev": "2-e5d07c00a0261c231dd2be9b26a6c0dc",
"type": "shoe-color",
"sku": "656F-PINSEC12",
"color": "black/houndstooth"
}
//--shoe sizes
{
"_id": "12b6289d558d7ceb5bef725091666ce5",
"_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
"type": "shoe-sizes",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"shoe-sizes": [
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
]
}
//--map/reduce
{
"_id": "_design/catalog",
"_rev": "4-de5baf04b485768de12d78e5a0e5aa5e",
"views": {
"item": {
"map": "function(doc)
{
if (doc.type === 'catalog-item')
{
emit([doc.sku, doc], null);
if (doc.shoe-colors)
{
for (var sc in doc.shoe-colors)
{
emit([doc.sku, Number(sc)+1], {_id: doc.shoe-colors[sc]._id});
for (var si in doc.shoe-colors[sc].shoe-images)
{
emit([doc.sku, Number(si)+1], {_id: doc.shoe-colors[sc].shoe-images[si]._id});
}
for (var sz in doc.shoe-colors[sc].shoe-sizes)
{
emit([doc.sku, Number(sz)+1], {_id: doc.shoe-colors[sc].shoe-sizes[sz]._id});
}
}
}
}
}"
}
}
}
There might be a better way of implementing this but I wanted to see if it was possible to have a document that has an array of linked documents whom also have an array of linked documents. But my map/reduce isn't returning anything. All it returns is:
{"total_rows":0,"offset":0,"rows":[
]}
I'm guessing that someone would not store all the information on a single document because, say we add a new show size or mark the shoe size as not available, this would mean one would have to pass back all the previous values to CouchDB just to update one field.
Hopefully my question makes sense Oo__oO
The trick with this is get away from thinking in terms of JOINs. Linked documents give you a technique to index one type of document based on properties of another. This works using a combination of two features:
CouchDB allows you to specify include_docs=true when querying a view to return the indexed documents along with the view results.
You can tell CouchDB to return ANY document by specifying an _id property in the view result. Note that you can still only return one document per result.
As an example, lets say you had documents
{
"_id": "111",
"type", "shoe",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"imageId": "222"
}
and
{
"_id": "222",
"type": "image",
"full-images": ["http://www.someurl.com/full/656F-PINSEC12.jpg"]
"thumbnail-images": ["http://www.someurl.com/thumb/656F-PINSEC12.jpg"]
}
then you could index images by SKU using the map function:
function(doc) {
if(doc.type === "shoe") {
emit(doc.sku, {_id: doc.imageId });
}
}
It's also important to realise that the map function only operates on the original document that was saved.
I think in your example, the "catalog item" and "shoe color" documents are redundant. You could define a map function to index the "shoe image" and "shoe size" documents by SKU e.g.
function(doc) {
if(doc.SKU) {
emit(doc.SKU, null);
}
}
Assuming this was assigned to the view "item-details", your query:
https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22
should return
{
"total_rows":2,
"offset":0,
"rows":
[
{
"id":"7b547bae4ac911c6f05b97eba6cb355a",
"key":"656F-PINSEC12",
"value":null,
"doc":{
"_id": "7b547bae4ac911c6f05b97eba6cb355a",
"_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
"type": "shoe-images",
"sku": "656F-PINSEC12",
"color": "Black/Houndstoot",
"full-images": [
"http://www.someurl.com/full/656F-PINSEC12.jpg"
],
"thumbnail-images": [
"http://www.someurl.com/thumb/656F-PINSEC12.jpg"
]
}
},
{
"id":"12b6289d558d7ceb5bef725091666ce5",
"key":"656F-PINSEC12",
"value":null
"doc":{
"_id": "12b6289d558d7ceb5bef725091666ce5",
"_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
"type": "shoe-sizes",
"sku": "656F-PINSEC12",
"shoe-color": "black/houndstooth",
"shoe-sizes": [
{
"size": 5,
"IsSizeAvailable": true
},
{
"size": 6,
"IsSizeAvailable": true
},
{
"size": 7,
"IsSizeAvailable": true
},
{
"size": 8,
"IsSizeAvailable": true
},
{
"size": 9,
"IsSizeAvailable": true
},
{
"size": 10,
"IsSizeAvailable": true
},
{
"size": 11,
"IsSizeAvailable": true
},
{
"size": 12,
"IsSizeAvailable": true
},
{
"size": 13,
"IsSizeAvailable": true
},
{
"size": 14,
"IsSizeAvailable": true
}
]
}
]
}
If you wanted to combine these results into a single JSON document, you could look at using a list function to generate custom JSON output. However, I'm not sure that gains you much.
It looks like you'd generally be better off with a more granular data model (e.g. each shoe / size combination could be a separate doc) and use map functions to aggregate the data for a given SKU.