CouchDB Design Doc...Save Failed: Expression Does Not Eval To a Function - couchdb

So I'm trying to create a design doc in CouchDB and there's a slight problem. This is for a robotics team scouting system. The design doc is supposed to check if a user has the role "marea". If they do, then they are allowed to input a document into the database. Then the design doc should take the JSON field "points" and average it if the "team" fields match. The averaged value should be merged back into the database. If the user does not have the "marea" role, then they should be restricted from inputting any docs. Please let me know what you think of the below code, and I would also like some advice on the error message I get. I'm able to save the design doc just fine, but its functioning is a little iffy. It prevents the user from creating a new doc with a "points" value even when that user has the role "marea". The exact error message is:
Save failed: Expression does not eval to a function. (function(newDoc, oldDoc, userCtx, secObj) { if ((userCtx.roles.indexOf("2018marea") !==
-1) || (userCtx.name == oldDoc.name)) { if (!doc) { if ("id" in req && req["id"]) { return [{"_id": req["id"]}, "New Doc"] emit(null, "points") var pointsArray = ["points"], thisTotal = 0, thisAverage = 0; for(var i = 0;i < pointsArray.length; i++) { thisTotal+ = pointsArray[i]; } thisAverage = (thisTotal/pointsArray.length); } return [null, "Empty Database."] } doc["New Doc"] = thisAverage; doc["edited_by"] = req["userCtx"]["name"] return [doc, "Edited Data."] } else { return [null, "Cannot Overwrite Data"] } } )
How do I fix this problem so that the design doc carries out its intended function?
{
"_id": "_design/marea",
"language": "javascript",
"validate_doc_update": "function(newDoc, oldDoc, userCtx, secObj) {\r\n\r\n if ((userCtx.roles.indexOf(\"2018marea\") !== -1) || (userCtx.name == oldDoc.name)) { \r\n \r\n if (!doc) {\r\n \r\n if (\"id\" in req && req[\"id\"]) {\r\n \r\n return [{\"_id\": req[\"id\"]}, \"New Doc\"] \r\n emit(null, \"points\")\r\n var pointsArray = [\"points\"], thisTotal = 0, thisAverage = 0;\r\n for(var i = 0;i < pointsArray.length; i++) {\r\n \r\n thisTotal+ = pointsArray[i];\r\n \r\n }\r\n \r\n thisAverage = (thisTotal/pointsArray.length); \r\n \r\n }\r\n \r\n return [null, \"Empty Database.\"]\r\n \r\n }\r\n \r\n doc[\"New Doc\"] = thisAverage;\r\n doc[\"edited_by\"] = req[\"userCtx\"][\"name\"] \r\n return [doc, \"Edited Data.\"] \r\n\r\n } else {\r\n \r\n return [null, \"Cannot Overwrite Data\"]\r\n \r\n }\r\n } "
}

The error is pretty obvious: You function is not valid
There's a space between + = : { thisTotal+ = pointsArray[i]; }
You forgot some semi colon between few statements:
"New Doc"] ; emit(null, "points"); var pointsArray
This should work better:
function(newDoc, oldDoc, userCtx, secObj) {
if ((userCtx.roles.indexOf("2018marea") !== -1) || (userCtx.name == oldDoc.name)) {
if (!doc) {
if ("id" in req && req["id"]) {
return [{
"_id": req["id"]
}, "New Doc"];emit(null, "points"); var pointsArray = ["points"],
thisTotal = 0,
thisAverage = 0;
for (var i = 0; i < pointsArray.length; i++) {
thisTotal += pointsArray[i];
}
thisAverage = (thisTotal / pointsArray.length);
}
return [null, "Empty Database."]
}
doc["New Doc"] = thisAverage;
doc["edited_by"] = req["userCtx"]["name"]
return [doc, "Edited Data."]
} else {
return [null, "Cannot Overwrite Data"]
}
}

Related

Azure speech to text with numbers

A use case for my app is to convert speech (single word utterances) to text. I need to use Azure speech to text for this. Sometimes the speech needs to be converted into an integer - I need to submit the response as a quantity for example.
My question is is there anyway, via the REST API, to tell the speech to text service I want a numeric result? Currently it is returning things like 'one' instead of '1' and 'free' instead of '3'. I don't think there is a way to do this from the documentation but I wanted to see if anyone else has solved this problem before I think of a way around it.
This is the code I am using in my proof of concept project:
public static async Task SpeechToTextAsync(MemoryStream data, ISpeechResultCallback callBack)
{
string accessToken = await Authentication.GetAccessToken();
IToast toastWrapper = DependencyService.Get<IToast>();
if (accessToken != null)
{
toastWrapper.Show("Acquired token");
callBack.SpeechReturned("Acquired token");
using (var client = new HttpClient())
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://westus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-GB&format=detailed");
request.SendChunked = true;
request.Accept = #"application/json;text/xml";
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version11;
request.Host = "westus.stt.speech.microsoft.com";
request.ContentType = #"audio/wav; codecs=audio/pcm; samplerate=16000";
// request.Headers["Ocp-Apim-Subscription-Key"] = Program.SubscriptionKey;
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.AllowWriteStreamBuffering = false;
data.Position = 0;
byte[] buffer = null;
int bytesRead = 0;
using (Stream requestStream = request.GetRequestStream())
{
buffer = new Byte[checked((uint)Math.Min(1024, (int)data.Length))];
while ((bytesRead = data.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
// Flush
requestStream.Flush();
}
try
{
string responseData = null;
using (WebResponse response = request.GetResponse())
{
var encoding = Encoding.GetEncoding(((HttpWebResponse)response).CharacterSet);
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream, encoding))
{
responseData = reader.ReadToEnd();
AzureSTTResults deserializedProduct = JsonConvert.DeserializeObject<AzureSTTResults>(responseData);
if(deserializedProduct == null || deserializedProduct.NBest == null || deserializedProduct.NBest.Length == 0)
{
toastWrapper.Show("No results");
callBack.SpeechReturned("No results");
}
else
{
toastWrapper.Show(deserializedProduct.NBest[0].ITN);
callBack.SpeechReturned(deserializedProduct.NBest[0].ITN);
}
}
}
}
}
catch (Exception ex)
{
toastWrapper.Show(ex.Message);
callBack.SpeechReturned(ex.Message);
}
}
}
else
{
toastWrapper.Show("No token required");
callBack.SpeechReturned("No token required");
}
}
And here is an example of the result that I would like to be '1':
{
"RecognitionStatus": "Success",
"Offset": 0,
"Duration": 22200000,
"NBest": [
{
"Confidence": 0.43084684014320374,
"Lexical": "one",
"ITN": "One",
"MaskedITN": "One",
"Display": "One."
}
]
}
I suggest to use this nuget from Microsoft. It works like a charm, here an example.
NumberRecognizer.RecognizeNumber("I have two apples", Culture.English)
According to the offical document Speech-to-text REST API, there is no option can help converting the numberic words to numbers.
Considering for the numberic words in English have the pattern in syntax, you can use a simple algorithm to implement the feature for converting words to numbers. As references, you can follow these below to write your own one in C# by yourself.
Converting words to numbers in c++
Translate (Convert) Words to Numbers RRS feed in SQL Server
Words in Numbers
Hope it helps.

values get undefined after then of promise nodejs

I'm facing a problem with my code... I make a query to my DB to check if a mac address of a array of macs is on the DB. If I have any result I return the count of macs in my DB and if is > 0 then I don't add nothing cause the mac already is listed, but if my result.count = 0 then I will add a new record.
My new record just have the mac address. For this I'm trying:
var countRepetidos = 0
var countPromises = []
if (obj.data.list != {} && obj.data.list.length > 0) {
var aux = obj.data["list"]
countRepetidos = 0
for (var i = 0; i < aux.length; i++) {
countPromises.push(Database.Probing.getMacAdress(aux[i]).then(function(data) {
console.log("probing countPromises aux[i] ", aux[i])
if (data.count > 0) {
countRepetidos += 1
} else {
Database.Probing.addMac(aux[i])
}
return Promise.resolve()
}))
}
Promise.all(countPromises).then(() => {
dataRepeated = [obj.data.stats.since, countRepetidos]
listaRepeated.push(dataRepeated)
console.log("probing listaRepeated --> ", listaRepeated)
if (listaRepeated != [] && (listaRepeated[0][0] != undefined && listaRepeated[0][1] != undefined)) {
Database.Probing.getLastTimestamp("probing_repeated", device.id).then(function(data) {
var lastTimestamp = data.date_part
console.log('probing lastTimestamp ', lastTimestamp * 1000)
if (lastTimestamp != listaRepeated[0][0] / 1000) {
Controllers.Agregate.agregateData("probing_repeated", 5 * 60, listaRepeated, dbHistConnectionString, device.id, device.network_id, device.organization_id, ["time", "clients"])
}
})
}
})
}
The problem is after the then of Database.Probing.getMacAddress my aux[i] gets undefined and I need this value to insert into my DB.
Anyone can help?
You need to preserve the value of i. You can do this way:
for (var i = 0; i < aux.length; i++) {
(function(i) {
countPromises.push(
Database.Probing.getMacAdress(aux[i]).then(function(data) {
console.log("probing countPromises aux[i] ", aux[i])
if (data.count > 0) {
countRepetidos += 1
} else {
Database.Probing.addMac(aux[i])
}
return Promise.resolve()
}))
})(i)
}
Edit 1: As suggested by #lain, use let over var
for (let i = 0; i < aux.length; i++) {}

TypeError: Object function Buffer(subject, encoding, offset) {

I have an error when I use my express server with buffer it crashes in this line:
authorization = Buffer.from(authorization, 'base64').toString('utf8')
The error message is:
TypeError:
Object function Buffer(subject, encoding, offset) { if (!(this instanceof Buffer)) { return new Buffer(subject, encoding, offset); } var type; if (typeof offset === 'number') { if (!Buffer.isBuffer(subject)) { throw new TypeError('First argument must be a Buffer when slicing'); } this.length = +encoding > 0 ? Math.ceil(encoding) : 0; this.parent = subject.parent ? subject.parent : subject; this.offset = offset; } else { switch (type = typeof subject) { case 'number': this.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': this.length = Buffer.byteLength(subject, encoding); break; case 'object': this.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: throw new TypeError('First argument needs to be a number, ' + 'array or string.'); } if (this.length > Buffer.poolSize) {this.parent = new SlowBuffer(this.length); this.offset = 0; } else if (this.length > 0) { if (!pool || pool.length - pool.used < this.length) allocPool(); this.parent = pool; this.offset = pool.used; pool.used = (pool.used + this.length + 7) & ~7; } else { this.parent = zeroBuffer; this.offset = 0; } if (typeof subject !== 'number') { if (type === 'string') { this.length = this.write(subject, 0, encoding);} else if (Buffer.isBuffer(subject)) { if (subject.parent) subject.parent.copy(this.parent, this.offset, subject.offset, this.length + subject.offset); else subject.copy(this.parent, this.offset, 0, this.length); } else if (isArrayIsh(subject)) { for (var i = 0; i < this.length; i++) this.parent[i + this.offset] = subject[i]; } } } SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length); } has no method 'from'
Your Buffer object does not contain any from function. You don't use the correct Buffer object. I guess you want to use the Node.js Buffer. Make sure that you really use it and you have an up-to-date version.

jQuery-Validation-Engine required only if value of another field is x or y

"requiredInFunction": {
"regex": "none",
"func": function(field, rules, i, options){
if (field.val() === '' && $('#CartItem_vision').val()==="Progressive") {
return false;
}
if (field.val() === '' && $('#CartItem_vision').val()==="Bifocal")
{
return false;
}
else
{
return true;
}
},
"alertText": "Addition is Required"
},
validate[custom[requiredInFunction]]
This validation does not do anything.
unless I put validate[required, custom[requiredInFunction]], but it becomes required even if the CartItem_vision is not "Progressive" or "Bifocal". I want them to be only required if value is "Progressive" or "Bifocal".
In your function you can add
rules.push('required');
Like this :
function checkCell(field, rules, i, options){
if ($('#cellNum').val().length > 0 && field.val().length == 0) {
rules.push('required');
return "Provider necessary with phone number";
}
}
This means that if #cellNum is populated then the provider is necessary.
The initialization is :
<select name="provider" id="provider" class="validate[funcCall[checkCell]">

Couchbase/CouchDB grouping by part of key and ordering by another part

I've got a database of messages between users. Document looks like:
"_id": "msg_0bec56c1-cbfb-47a5-8882-4a61fec332cd",
"_rev": "1-00000eda4d07c93d0000009100000112",
"$flags": 0,
"$expiration": 0,
"Date": 1340280439303,
"OwnerId": 35,
"RcptId": 37,
"SndrId": 35,
"Text": "msg5",
"Unread": false,
"id": "0bec56c1-cbfb-47a5-8882-4a61fec332cd",
"type": "msg"
For each message it stores 2 documents with different OwnerId. I need to get the lastest message between one specified person and 10 uniqe "pen friends" ordered by last message date.
My query params:
descending=true&endkey=[35,35]&startkey=[35,35,"{}"]&limit=10&skip=0
My map function:
function (doc) {
if (doc.type == "msg"){
emit([doc.OwnerId, doc.SndrId, doc.Date, doc.RcptId], doc);
emit([doc.OwnerId, doc.RcptId, doc.Date, doc.SndrId], doc);
}
}
As a result I get list of messages for desired account. Last value (4th) in key is that value on which we should group values.
Groupping with group level 4 not working because dates are different.
Here is my new map function that does exactly what i've wanted BUT only if I have one server.
var uniqPairs = [];
function(doc){
if (doc.type == "msg"){
if (doc.OwnerId == doc.SndrId){
if (uniqPairs.indexOf(doc.OwnerId + "_" + doc.RcptId) == -1){
uniqPairs.push(doc.SndrId + "_" + doc.RcptId);
uniqPairs.push(doc.RcptId + "_" + doc.SndrId);
emit([doc.OwnerId, doc.Date], {"owner": doc.OwnerId, "from":doc.SndrId, "to":doc.RcptId});
}
}
if (doc.OwnerId == doc.RcptId){
if (uniqPairs.indexOf(doc.OwnerId + "_" + doc.SndrId) == -1){
//uniqPairs.push(doc.SndrId + "_" + doc.RcptId);
uniqPairs.push(doc.RcptId + "_" + doc.SndrId);
emit([doc.OwnerId, doc.Date], {"owner": doc.OwnerId, "from":doc.SndrId, "to":doc.RcptId});
}
}
}
}
So for cluster I sacrificed "ordering by date" and got such functions for map/reduce:
Map:
function (doc) {
if (doc.type == "msg"){
if (doc.OwnerId == doc.SndrId){
emit([doc.OwnerId, doc.RcptId, doc.Date], {"Date":doc.Date, "OwnerId":doc.OwnerId, "RcptId":doc.RcptId, "SndrId":doc.SndrId, "Text":doc.Text, "Unread":doc.Unread, "id": doc.id, "type":doc.type});
} else {
emit([doc.OwnerId, doc.SndrId, doc.Date], {"Date":doc.Date, "OwnerId":doc.OwnerId, "RcptId":doc.RcptId, "SndrId":doc.SndrId, "Text":doc.Text, "Unread":doc.Unread, "id": doc.id, "type":doc.type});
}
}
}
Reduce:
var tmp = [];
var t = [];
function findRecent(arr){
var max = 0;
var maxId = 0;
for (var i in arr){
if (arr[i].Date > max){
max = arr[i].Date;
maxId = i;
}
}
return arr[maxId];
}
function(k,v,r){
if (!r){
tmp.push(v);
}
else{
tmp.push(v);
}
if (r){
for (var i1 in tmp[0])
{
t.push(tmp[0][i1]);
}
} else {
return findRecent(v);
}
return findRecent(t);
}
If someone knows better solution (i.e. how to oreder results by date) - you're welcome to answer.

Resources