Using Design Documents to add an element to a list - couchdb

Users can press a button on my website to declare interest in a course. For every course there is a document in my CouchDB installation. These documents look like this:
{
"_id": "...",
"_rev": "...",
"name": "...",
"description": "...",
"userList": []
}
When a users presses the button his name should be added to "userList". I wrote a Design Document for this:
{
"_id": "_design/updateList",
"_rev": "...",
"updates": {
"addUser": "function(doc, req) {doc['userList'] = req['name']; var message = 'user added'; return [doc, message];}",
}
}
I know that this cannot be the right solution because the list can never be longer than one user name like this. However, not even that works. When I press on the button, the line ""userList": []" disappears from the corresponding document.
What's the problem here? I use PHP-On-Couch to run the Design Document but there shouldn't be any problems in my PHP code. I see in the CouchDB log that CouchDB receives the user name just fine.

The direct problem is that a req object does not have a field called "name" so:
doc['userList'] = req['name']
is equivalent to:
doc['userList'] = undefined
you may have meant to use userCtx req.userCtx.name directly if users are logged in, or req.query.name if you have added it as a parameter.
More generally, you probably meant to push their name on to the array which is probably fine if class sign up isn't very high volume. An alternate approach is to generate an independent document for each user+class and rely on views to count them.

Related

Mongodb flexible email notification conditions

I am searching for a way to store conditions in mongodb, to be queried and checked, then do something as a result of the condition check.
First off here is an example of the event object that I am considering
{
"name": "My Event",
"created": 1490726092221,
"startDate": 1490726092221,
"endDate": 1490726097810,
"notifications": [
{
"message": "{event.Name} Created", // message template
"status": 0, // 0=initialized 1=failed 2=sent
"sendDate": null, // date that the notification was sent
"sentTo": ["c2a34dfg32c1d4583e73a123"] //members to send notification to
"criteria": {
"script": "event.created >= 0 && this.status < 2"
}
}
],
"members": [
{
"_id": "c2a34dfg32c1d4583e73a123" // Reference to the user
}
]
}
The use case, I want to have customizated notifications for an event. So if an event is scheduled it could have notifications for when it is created, when the event start date is within a few days, when a member joins etc. While I could code all of these into javascript functions and correspond to them by an enum for the notification criteria, or have hooks for when certain events happen, this seems like a strict approach.
What I am envisioning is possibly a scripting language that can be stored as a string on the document, which can be queried and evaluated, which will return a boolean to trigger the notification or not.
The script would need to have the event as an input variable, as well as a few special input variables to be available to the script.
This could be done with javascript and eval() but that scares me. Are there any other tools that can be used for this use case? Or, are there any suggestions for a better approach to this problem?
Sounds like you are building a workflow engine with a MongoDB back end. I would start by researching things like the ones listed in this answer Workflow engine in Javascript

Creating view to check a document fields for specific values (For a simple login)

I'm very new to cloudant , so pardon me for this question. I am creating a simple mobile game login system which only checks for username(email) and password.
I have several simple docs that are in this format
{
"_id": "xxx",
"_rev": "xxx",
"password": "3O+k+O8bxsxu0KUlSBUiww==", --encrypted by application beforehand
"type": "User",
"email": "asd#asd.com"
}
Right now I can't seem to get the correct 'Formula' for creating this view (map function) whereby I would do a network request and pass it both the email and password. If there is a doc that matches the email, then check the doc.password against the passed value. If it matches, the function should return a simple "YES".
For now my map function is as follows, but this just returns all the docs .
function(doc) {
if (doc.email){
index("password", doc.password, { store : true });
if (doc.password){
emit("YES");
}
}
}
It may be my request format is also wrong. Right now it is as follows. Values are not real, only for format checking
https:/etcetc/_design/app/_view/viewCheckLogin?q=email:"asd#asd.com"&password:"asd"
It looks like you have misunderstood how views are supposed to work. In general you cannot perform logic to return a different result based on the request. Query parameters in a view request can only be used to limit the result set of view entries returned or to return grouped information from the reduce function.
To determine if there is a match for a given username and password you could emit those values as keys and then query for them. This would return the view entry for those keys or an empty list if there was no match. However I'd be very cautious about the security here. Anyone with access to the view would be able to see all the view entries, i.e. all the usernames and passwords.

mongo update query to ignore few fields in update operation

I am using Nodejs based mongoskin driver for mongo database operation. I want to update my document however don't want to update few fields. Following are more details.
Request for add:
{
"name": "Theme Name",
"description": "Theme Description",
"createdByUserId": "53651221b25521601a5c9530",
}
Request for update:
{
"_id":"53555ef203dabf282b750a81"
"name": "Theme Name",
"categoryId": "53555ef203dabf282b750a81",
"description": "Theme Description",
"createdByUserId": "53651221b25521601a5c9530",
"updatedByUserId": "5675561b25521601a5c9530",
"dateCreated": ISODate("2014-05-19T19:47:26.603Z"),
"dateUpdated": ISODate("2014-05-19T19:49:28.203Z"),
}
I want to ignore following field send by client.
1. createdByUserId
2. dateCreated
For time being I am taking following approach in update operation:
1. Read collection for given _id
2. Read these above two fields from database and update the request and then perform database update operation
Looking help for clean approach.
Your request for update actually does the following: it replaces everything in the document with the values provided by the request (except for the "_id" of course, which is immutable). What you want is what is called a "partial update" in mongosphere. Please have a look into the $set operator. So what you would do is something like:
db.yourcollection.update({"_id":"53555ef203dabf282b750a81"},
{$set:
{
"categoryId":"53555ef203dabf282b750a81",
"updatedByUserId":"5675561b25521601a5c9530",
"dateUpdated":ISODate("2014-05-19T19:49:28.203Z")
}
}
)
As far as I know there is now way of sending a complete document to a mongo[s|d] and tell it to only skip certain fields.

Saving a Person or Group field using REST

Does anyone know how to save a Person field using REST?
I have tried the following and it works:
{
"__metadata": { "type": "SP.Data.SomeListListItem" } ,
"MyPersonFieldId" : 1
}
But this only works if you know the ID. I don't have that! How can I get it? I have the key which is i.0#w|domain\userName.
I tried the following and it doesnt work either:
{
"__metadata": { "type": "SP.Data.SomeListListItem" } ,
"MyPersonField" : { "__metadata": { "type": "SP.Data.UserInfoItem" }, "Name": "i.0#w|domain\userName" }
}
Any ideas?? Thanks!
I haven't done this with a Person field, but I did do something similar with a managed metadata field. I basically had to pass in additional information as an object to create the value in the field.
See if passing in the ID of the user along with the name works. I'm about to try this myself as I have the same need.
{
"MyPersonField": { "Name": "i.0#w|domain\userName", "ID": 1 }
}
EDIT: Ok, updating this field is easier than I thought. I was able to perform the update by simply passing in the ID of the user to the Id field:
{
"MyPersonFieldId": 1
}
This means the user should already be in the site collection, so if the user doesn't exist the request will fail.
Use the below code to get Current User ID to save user under People and group column. People column name is Requestor. But to save user we have to specify column name as RequestorId
var userid = _spPageContextInfo.userId; // To get current user ID
var itemProperties={'Title':vTitle,'RequestorId':userid};
The thing is that User information is a lookup field thereby MyPersonField does not exist on your SharePoint list if you use an OData endpoint, I really don't know how to save data but same problem happened to me when I tried to read a user.
for example {server}/{api}/list/getbytitle('mylist')/items does not return MyPersonField instead return MyPersonFieldId.
But if we use:
{server}/{api}/list/getbytitle('mylist')/items/?$select=*,MyPersonField/Name&$expand=MyPersonField
We are able to work with MyPersonField lookup values.

How could I determine all possible keys of a CouchDB database?

I am creating one application where for every product I have one database and I will create different document based on date. The keys in documents could be different and depend upon user, what he provides. Assumption is user will keep giving same key for tracking with changed value over time. In the end, I need to know all possible keys before creating automatic views on them.
Example:
If I had DB, say, test. It contains, say, two documents,
1. {
"_id":"1",
"_rev":"1-"
"type": "Note",
"content": "Hello World!"
}
2. {
"_id":"2",
"_rev":"1-"
"type": "Note",
"content": "Beyond Hello World!",
"extra":"Boom"
}
Then I want to list all keys in this DB. So, answer should be _id,_rev,type,content and extra.
These keys are dynamic and depend upon users. So, I couldn't assume that I knew them in advance.
I have never used stackoverflow before, I saw your question when trying to solve this problem myself so I have signed up. I think this solves your problem:
create a view where "views" includes this:
{
"keys": {
"map": "function(doc) { for (var thing in doc) { emit(thing,1); } }",
"reduce": "function(key,values) { return sum(values); }"
}
}
then query on that view with group=true e.g.:
http://localhost:5984/mydb/_design/myview/_view/keys?group=true
you should get back a list of all the keys in your database and a count of how often the occur.
does this help?

Resources