Couchdb retrieving documents in array - javascript

The following document is a small example which is stored in CouchDB.
{
"_id": "Test4",
"referenceName": "refA",
"positions": {
"A": 422,
"B": 5442
},
"properties": [
{
"tId": "ARQ3TPR7",
"pos": 4609,
"zIds": [
"z0003674",
"z0008150",
"z0016020",
"z0016021"
]
}
],
...
}
The below map function does not work and I don't know how to fix it. I got Error: compilation_error Expression does not eval to a function. I would like to retrieve _id, referenceName and positions.
{
"_id": "_design/doc",
"views": {
"by_zIds": {
"map": "function(doc) {
for (var i in properties {
var d = doc.properties[i];
for (var x in d.zIds){
emit(d.zIds[x], doc);
}
}
}"
}
},
"language": "javascript"
}
How is it possible to fix the above map function in order to use the view like /dbname/_design/doc/_view/by_zIds?key="z0016021"?

There is a ) missing after properties in your map function. There might be other typos. I would suggest that you write your map functions in an editor with syntax highlighting and them locally to catch those kinds of errors early.
EDIT: There are several other problems with your map function, all of which can be found with unit testing and/or debugging. This should work, but I haven't tested it:
function(doc) {
for (var d in doc.properties) {
for (var x in d.zIds) {
emit(x, doc);
}
}
}

I solved it in the following way, but I am not sure whether it is the best way
function(doc) {
for (var i in doc.properties) {
for (var x in doc.properties[i].zIds) {
emit(doc.properties[i].zIds[x], doc);
}
}
}
Is it possible to improve?

Related

Filter Array Using Partial String Match in Javascript

I have an array of objects where the value I need to filter on is buried in a long string. Array looks like:
{
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
},
So if I wanted to grab all the partnerId objects where value includes parent_sku how would I do that?
console.log(data.value.includes('parent_sku') returns cannot read property 'includes' of null.
EDIT:
Didn't think this mattered, but judging by responses, seems it does. Here's the full response object:
Response body: {
"data": {
"configurationByCode": [
{
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
}
I'm passing that into a re-usable function for filtering arrays:
const parentSkuPartners = filterArray(res.body.data.configurationByCode, 'parent_sku');
Function:
function filterArray(array, filterList) {
const newList = [];
for (let i = 0; i < array.length; i += 1) {
console.log('LOG', array[i].data.value.includes('parent_sku');
}
}
The problem is somewhere else. The code you've tried should work to find if a value contains a string – I've added it the snippet below and you'll see it works.
The issue is how you are accessing data and data.value. The error message clearly states that it believes that data.value is null. We would need to see the code around it to be able to figure out what the problem is. Try just logging to console the value of data before you run the includes function.
const data = {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}", "partnerId": 1
};
console.log('includes?', data.value.includes('parent_sku'));
You can use data.value.includes('parent_sku') as you have suggested. The issue here is that your object is nested inside an unnamed object.
try:
"data": {
"value": "{\"cols\":[\"parent_sku\"],\"label\":\"Style\",\"description\":\"Enter Style.\",\"placeholderText\":\"Style 10110120103\"}",
"partnerId": 1
}
The problem was some of the values for value were null. Adding an extra conditional fixed it:
if (array[i].data.value !== null) {
Use lodash includes, and lodash filter like
let configurationByCode = [{
data: {
value: {
cols:["parent_sku"],
label:"Style",
description:"Enter Style.",
placeholderText:"Style 10110120103"
},
"partnerId": 1
}
}, {
data: {
value: {
cols:["nothing"],
label:"Style",
description:"Enter Style.",
placeholderText:"Style 10110120103"
},
"partnerId": 2
}
}];
let wantedData = _.filter(configurationByCode, (config) => {
return _.includes(config.data.value.cols, 'parent_sku');
});
console.log( wantedData );
https://jsfiddle.net/76cndsp2/

MongoDB using parameter for nested location

have a little newbe problem although I couldn't find a solution for similar problems, that worked for me.
Here is my collection:
{
"_id": ObjectId("5bc712851224ceec702d9bdf"),
"index": "123456",
"name": "Jan",
"surname": "Nowak",
"grades": {
"IABD": [
2,
3.5,
4
],
"NPAD": [
4,
4,
5
]
}
}
now I need to push additional grades to specific (function parameters) courses.
So I tried tackling it on a few levels and I'd love somebody to walk me through it according to this:
First I wanted to succeed not passing course as a parameter:
function add_grade(index="123456", course="IABD", grade=5.5)
{
db.students.update( {"index" : index }, { $push: { "grades" : { "IABD" : grade } } } );
}
well nothing happened (grade was not added to the list of grades)
I wanted to see some result, so I wanted to see if $set would work and it did!
function add_grade(index="123456", course="IABD", grade=5.5)
{
db.students.update( {"index" : index }, { $set: { "grades" : { "IABD" : grade } } } );
}
but it threw away my entire grades object (as expected). At least I know I'm on the right track.
Question 1: Why $push didn't work the way I expected
Question 2: how to use course parameter in set/push?
Just to clarify Q2, I'm not lazy, I've tried many approaches, none of which worked, please help!
You can try below query. That push 6 into IABD
db.getCollection('students').update( { "index": "123456" }, { $push: { "grades.IABD" : 6 } });
$push is not working the way you are expecting because the array field is in an embedded document and to push you need to use
dot notation i.e. instead of
{ "$push": { "grades" : { "IABD" : grade } } }
what you need is to specify the field as dot notation
{ "$push": { "grades.IABD" : grade } }
To use the course parameter in push you would want to create an update object that holds the dot notation
{ "grades.<course>" : grade }
for example
var course = "IABD";
var grade = 5.5;
var update = {};
update["grades." + course] = grade;
printjson(update) // prints { "grades.IABD" : 5.5 }
So your function will look like
function add_grade(index="123456", course="IABD", grade=5.5) {
var update = {};
update["grades." + course] = grade;
db.students.update(
{ "index" : index },
{ "$push": update }
);
}

nodejs exported variable is not reusable on second hit

I am exporting a variable which is an array from file1.js:
// file1.js
const myArray = [
{
"name": "Judah Hendricks",
"email": "diam#lobortis.net",
"hobbies": [
{
"sports": "tennis",
"recent": true
},
{
"sports": "football",
"recent": false
},
{
"sports": "volleyball",
"recent": false
}
]
},
{
"name": "Jakeem Olsen",
"email": "at#tellus.org",
"hobbies": [
{
"sports": "swimming",
"recent": false
},
{
"sports": "running",
"recent": true
}
]
}
];
module.exports = { myArray };
and I am using it inside a route:
//main.js
const { myArray } = require('./file1.js');
router.get('/getData', (req, res) => {
dataBase.users.findOne({ email: req.user.email }, function(error, data){
if (data){
const myDataClone = [...myArray];
let newData = [];
newData = myDataClone.map( dt => {
dt.oldHobbies = []
for (let i = 0; i < dt.hobbies.length; i++) { // Cannot read property 'length' of undefined
if (dt.hobbies[i].recent) {
dt.recentHobby = dt.hobbies[i];
} else {
dt.oldHobbies.push(dt.hobbies[i]);
}
}
delete dt.hobbies;
return dt;
})
return res.status(200).json({userInfo: newData})
} else {
// do another
}
});
}
when I hit this route for the first time, it returns the expected data. my problem is when I revisit this route for the second time, I get Cannot read property 'length' of undefined for the dt.hobbies .
Could somebody help me understand what is wrong here and how to fix it?
The problem is here:
const myDataClone = [...myArray];
You're only shallow cloning the array, not deep cloning it; although the myDataClone array is different from myArray, the objects inside both arrays refer to the same objects in memory. So, when you
delete dt.hobbies;
the original object's hobbies property gets deleted as well, which means when you try to access the hobbies property of the object later, errors are thrown.
Fix it by making a deep clone at the beginning instead:
const myDataClone = JSON.parse(JSON.stringify(myArray));
As mentioned here, JSON.parse(JSON.stringify()) is probably the quickest way to deep clone objects. There are other methods like adding jQuery as a dependancy and using jQuery.extend, or writing your own custom cloning function, but serializing and deserializing works just fine.

rule engine function inside Meteor bindEnvironment losing its this object

var process_request_rule = [
{
"name": "rule-name",
"condition": Meteor.bindEnvironment(function (R) {
R.when(this.request.type == 'some-type');
})
}];
In the above code, this.request was getting undefined as this was pointing to Meteor object not to the function object. After researching got to know that using arrow functions might resolve the issue. Tried using that as shown below.
var process_request_rule = [
{
"name": "rule-name",
"condition": Meteor.bindEnvironment((R) => {
R.when(this.request.type == 'some-type');
})
}];
Still no luck, Please help me binding this object
You can either drop using Meteor.bindEnvironment or just use second argument passed to condition callback — it is the same as supposed this. https://github.com/mithunsatheesh/node-rules/blob/master/lib/node-rules.js#L94
Something like this:
var process_request_rule = [
{
"name": "rule-name",
"condition": Meteor.bindEnvironment(function(R, session) {
R.when(session.request.type == 'some-type');
})
}];

How can i build this json format in javascript?

I have this json where the values will be passed dynamically in javascript,
{
"User": {
"-xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"memNum": "70000211981",
"orderslist": [
{
"orderid": "5119534",
"ordersource": "ONLINE",
"transactiondttm": "2014-01-09"
},
{
"orderid": "5119534",
"ordersource": "STORE",
"transactiondttm": "2014-01-09"
}
]
}
}
and i tried using this function to build the json but it doesnt seem to work,
function addOrder(req, orderId, orderSource, transactiondtm) {
req.User.orderslist.orderid.push(orderId);
req.User.orderslist.ordersource.push(orderSource);
req.User.orderslist.transactiondtm.push(transactiondtm);
}
Any suggestion..
The elements of orderslist are objects, not arrays, so you can't push onto them. You have to build them as objects, and then push that onto the orderslist array.
function addOrder(req, orderId, orderSource, transactiondtm) {
req.User.orderslist.push({ orderid: orderId,
ordersource: orderSource,
transactiondtm: transactiondtm });
}
Something like this should work.
function addOrder(req, orderId, orderSource, transactiondtm) {
req.User.orderslist.push({
"orderid": orderId,
"ordersource": orderSource,
"transactiondtm": transactiondtm
});
}
Javascript objects can be acessed like an array.
That way you can create dinamic members.
user = {"orderList":[]};
for(var i = 0; i<5; i++){
user.orderList[i] = {};
user.orderList[i]["orderId"] = i;
user.orderList[i]["orderSource"] = "STORE";
}
alert(user.orderList[0].orderSource);
//Shows "STORE"
you can see the code working here http://jsfiddle.net/wmgE6/

Categories

Resources