CouchDB filter timestamps in a reduce function - some sort of Date.now? - mapreduce

Can a Date.now type function be used in either map or reduce functions? Can it be used anywhere at all?
More specifically, the view must not cache the Date.now value.
Here is what I tested that only worked for the first run after a change to any view function:
function (doc){
var n = new Date();
if(doc.TimeStamp > n.getTime() - 30000){
emit(doc._id, doc);
}
}

The view rows will be refreshed only when the particular doc gets updated. But you can request the view for that result: emit the doc.TimeStamp as key and request the view with ?startkey=timestamp where timestamp is the value of now.getTime() - 30000.

Yes. var now = new Date() should work.
The condition must result in false. You can test it with the view:
function (doc) {
var now = new Date()
var timestamp = now.getTime()
emit(timestamp,null)
}
It will respond something like
{
"total_rows":1,
"offset":0,
"rows" :[{
"id":"ecd99521eeda9a79320dd8a6954ecc2c",
"key":1429904419591, // timestamp as key
"value":null
}]
}
Make sure that doc.TimeStamp is a number (maybe you have to execute parseInt(doc.TimeStamp)) and greater then timestamp - 30000
Two words about your line of code emit(doc._id, doc);:
To emit doc._id as key means maybe you doesn't need the view. Simply request the doc by GET /databasename/:id. Also to include doc._id in multipart keys or the value of the view row is mostly not necessary because its included in every row automatically as additional property. One valid reason would be when you want to sort the view over the doc ids.
To emit the doc as value is not recommended for performance reasons of the view. Simply add ?include_docs=true when you request the view and every row will have an additional property doc with whole doc in it.

Related

Create Inventory Adjustment giving an error

I am trying to create an inventory adjustment from a MAP/REDUCE script. the record from which i am setting the values is getting ftom a search in getInputData(). In map function i am loading that custom record and setting these values
var newcase_inv_Adj = record.create({type:'inventoryadjustment',isDynamic:true});
newcase_inv_Adj.setValue({fieldId:'account',value:creel_account});
newcase_inv_Adj.setValue({fieldId:'custbody_cp_adjreasoncode',value:creel_reasoncode});
newcase_inv_Adj.setValue({fieldId: 'custbody_c_from', value: name});
newcase_inv_Adj.selectNewLine({sublistId:'inventory'});
newcase_inv_Adj.setCurrentSublistValue({sublistId:'inventory',fieldId:'item',value:creel_item});
newcase_inv_Adj.setCurrentSublistValue({sublistId:'inventory',fieldId:'location',value:creellocation});
newcase_inv_Adj.setCurrentSublistValue({sublistId:'inventory',fieldId:'adjustqtyby',value:creel_weigh_oh});
var create_inv_detail = newcase_inv_Adj.getCurrentSublistSubrecord({sublistId: 'inventory',fieldId: 'inventorydetail'});
create_inv_detail.selectNewLine({sublistId:'inventoryassignment' });
create_inv_detail.setCurrentSublistValue({sublistId:'inventoryassignment',fieldId:'receiptinventorynumber',value: creel_casenumber});
create_inv_detail.setCurrentSublistText({sublistId:'inventoryassignment',fieldId:'binnumber',value: creel_bin });
create_inv_detail.setCurrentSublistValue({sublistId:'inventoryassignment',fieldId:'quantity',value: creel_weigh_oh });
create_inv_detail.commitLine('inventoryassignment');log.debug("N","commited inventoryassignment");
newcase_inv_Adj.commitLine({sublistId:'inventory'});log.debug("N","commited inventory");
var invAdjID = newcase_inv_Adj.save();log.debug("N","invAdjID : "+invAdjID);
But, I am getting this error as {"type":"error.SuiteScriptError","name":"UNEXPECTED_ERROR"
Is it because of Map/Reduce script?
I don't find anything wrong in the code.
Few suggestions:
- Follow the sequence: Set subsidiary value before you setvalue for account or any other mandatory field.
- First try with inventory items without serial numbers and see if you continue to face same problem.
- You need to make sure you all your variables has valid value (not null or undefined).
- First try doing this in a schedule script.

SAPUI5 - Input error on growing list, logic issue

I am having an issue with a growing list. Previously I had a normal list, but as it is limited to displaying 100 items, I need to now change this to a growing list, which works fine now and I can get over 100 items loaded when I've put the growing="true" growingThreshold="50" growingScrollToLoad="false" properties on the list.
But now I have an issue with one of the number inputs in the custom list, when entering a number it is not staying set (it has a liveChange event that updates a text component).
I've set a breakpoint in the controller to test and it seems to bug out when I am trying to set the data changes (red arrow on attached image).
Can anyone see the issue with the logic? If any additional code snippets are required I could provide them.
onReceivedQuantityChange: function (oEvent) {
// get model and data
var oModel = this.getOrderModel();
var oData = oModel.getData();
// get item from path
var oItem = this._getOrderItemByPath(oEvent.getSource().getBindingContext(this.MODEL_ORDERS).getPath());
// set received value
oItem._ReceivedValue = oEvent.getParameters().newValue * (oItem.ValuationPrice / oItem.Quantity);
// apply data changes
oModel.setData(oData);
},
Controller code image
onReceivedQuantityChange: function (oEvent) {
var oModel = this.getOrderModel()
var sItemPath = oEvent.getSource().getBindingContext(this.MODEL_ORDERS).getPath()
var iValuationPrice = oModel.getProperty(sItemPath + '/ValuationPrice')
var iQuantity = oModel.getProperty(sItemPath + '/Quantity')
var iNewValue = oEvent.getParameters().newValue
var iReceivedValue = iNewValue * (iValuationPrice / iQuantity)
oModel.setProperty(sItemPath + '/_ReceivedValue', iReceivedValue)
}
If you use setProperty() on the Model you're only chaning the specific Property in DataModel and Sapui5 is able to proceed bindingchanges on this Property only (and not the whole model).
If you get the data out of the model by getData() you are only getting a reference to this Object. If you change something on this Object, you don't have to set it back by setData() (it is already there because you used the reference of this Object).
But Sapui5 need to know that there was a specific change in datamodel and this is done by using setProperty()

How to get from CouchDB only certain fields of certain documents with a single request?

create a view that return only a subset of values from a document, each with its key and value within a json string. like if one given view returns a document as this following, Is it possible to get some fields information for a one request? thank you
{
"total_rows":10,
"offset":3,
"rows":[{
"id":"doc1",
"key":"abc123",
"value": {
"_id":"aaaa",
"_rev":"bbb",
"field1":"abc",
"field2":"bcd",
"field3":"cde",
"field4":"123",
"field5":"789",
"field6":"aa#email.com",
"field7":"ttt",
"field8":"iii",
"field9":[{
"field91":"tyui",
"field92":"55555"
}],
"field10"::"0000",
"field11"::"55555",
"field12"::"0030".........
}
}
I just want to create a view that returns some fields only the following:
{
"field1":"abc",
"field2":"bcd",
"field3":"cde",
"field4":"123",
"field5":"789",
"field6":"aa#email.com",
"field7":"ttt",
"field8":"iii",
"field9":[{
"field91":"tyui",
"field92":"55555"
}]
}
A map function that emits a new document with selected fields only. As an example, let's map field1 (a string) and field9 (an array) only:
function map(doc) {
emit(doc._id, {
field1: doc.field1,
field9: doc.field9
});
}
In the above example, each document will be fired with a key being the original doc ID and the value being the mapped fields you require.
This is useful if you are planning to add a reduce function later.
Depending on your use case, you may just want to emit the mapped objects:
function map(doc) {
emit({
field1: doc.field1,
field9: doc.field9
});
}
Please see http://guide.couchdb.org/draft/views.html
The documentation on building data views is pretty good, you can discover a lot by experimenting..

How would I modify this ember.js function to return an Enumerable or Array

I have just begun learning ember.js, I have followed some tutorials and created a working example here:
App.Track.reopenClass({
find: function() {
var tracks = [];
$.ajax({
url: 'http://ws.spotify.com/lookup/1/.jsonuri=spotify:album:6J6nlVu4JMveJz0YM9zDgL&extras=track',
dataType: 'json',
context: this,
success: function(data, textStatus, jqXHR) {
$.each(data.album.tracks, function(index, value) {
track_id = value.href.replace("spotify:track:", "");
tracks.addObject(App.Track.create(value));
// I would rather do something like:
// tracks[track_id] = App.Track.create(value)
});
}
})
return tracks;
}
});
This function hits an API and loops through the returned data to populate the tracks object (tracks.addObject(App.Track.create(value));) and return it.
Rather than getting an ordinary object back from this function, I would like to get an Enumerable / Array so I can manipulate it with filterProperty or pull out tracks by id (There is a track_id which I would like to use as the array index).
All of my attempts to use an array have broken ember's magical ability to update the view when the ajax call populates the tracks.
Can anyone modify http://jsfiddle.net/ZEzwn/ to return an Enumerable (preferably an Array) but still update the view automatically?
As your method already returns an Array (because you have Ember prototype extension enabled), doing:
var tracks = [];
is equivalent to
var tracks = Ember.A();
On ajax request success, you're just populating the array, so you could use Ember.Array methods like filterProperty.
Just one thing about using id as array key, you really SHOULD NOT, as Ryan Bigg says in its blog:
However, if the variant’s id is [something a little higher, like] 1,013,589,413, then you start to run into problems.
In that case, JavaScript would create a one billion, thirteen million, five hundred and eighty-nine thousand, four hundred and fourteen element array. All to store one value in, right at the end.
Ok this is now working, as louiscoquio pointed out, tracks IS an enumerable object and I can do stuff like
tracks.filterProperty('href', 'spotify:track:7x7F7xBqXqr0L9wqJ3tuQW')
tracks.getEach('name')
tracks.get('firstObject')

Adding item to filtered result from ember-data

I have a DS.Store which uses the DS.RESTAdapter and a ChatMessage object defined as such:
App.ChatMessage = DS.Model.extend({
contents: DS.attr('string'),
roomId: DS.attr('string')
});
Note that a chat message exists in a room (not shown for simplicity), so in my chat messages controller (which extends Ember.ArrayController) I only want to load messages for the room the user is currently in:
loadMessages: function(){
var room_id = App.getPath("current_room.id");
this.set("content", App.store.find(App.ChatMessage, {room_id: room_id});
}
This sets the content to a DS.AdapterPopulatedModelArray and my view happily displays all the returned chat messages in an {{#each}} block.
Now it comes to adding a new message, I have the following in the same controller:
postMessage: function(contents) {
var room_id = App.getPath("current_room.id");
App.store.createRecord(App.ChatMessage, {
contents: contents,
room_id: room_id
});
App.store.commit();
}
This initiates an ajax request to save the message on the server, all good so far, but it doesn't update the view. This pretty much makes sense as it's a filtered result and if I remove the room_id filter on App.store.find then it updates as expected.
Trying this.pushObject(message) with the message record returned from App.store.createRecord raises an error.
How do I manually add the item to the results? There doesn't seem to be a way as far as I can tell as both DS.AdapterPopulatedModelArray and DS.FilteredModelArray are immutable.
so couple of thoughts:
(reference: https://github.com/emberjs/data/issues/190)
how to listen for new records in the datastore
a normal Model.find()/findQuery() will return you an AdapterPopulatedModelArray, but that array will stand on its own... it wont know that anything new has been loaded into the database
a Model.find() with no params (or store.findAll()) will return you ALL records a FilteredModelArray, and ember-data will "register" it into a list, and any new records loaded into the database will be added to this array.
calling Model.filter(func) will give you back a FilteredModelArray, which is also registered with the store... and any new records in the store will cause ember-data to "updateModelArrays", meaning it will call your filter function with the new record, and if you return true, then it will stick it into your existing array.
SO WHAT I ENDED UP DOING: was immediately after creating the store, I call store.findAll(), which gives me back an array of all models for a type... and I attach that to the store... then anywhere else in the code, I can addArrayObservers to those lists.. something like:
App.MyModel = DS.Model.extend()
App.store = DS.Store.create()
App.store.allMyModels = App.store.findAll(App.MyModel)
//some other place in the app... a list controller perhaps
App.store.allMyModels.addArrayObserver({
arrayWillChange: function(arr, start, removeCount, addCount) {}
arrayDidChange: function(arr, start, removeCount, addCount) {}
})
how to push a model into one of those "immutable" arrays:
First to note: all Ember-Data Model instances (records) have a clientId property... which is a unique integer that identifies the model in the datastore cache whether or not it has a real server-id yet (example: right after doing a Model.createRecord).
so the AdapterPopulatedModelArray itself has a "content" property... which is an array of these clientId's... and when you iterate over the AdapterPopulatedModelArray, the iterator loops over these clientId's and hands you back the full model instances (records) that map to each clientId.
SO WHAT I HAVE DONE
(this doesn't mean it's "right"!) is to watch those findAll arrays, and push new clientId's into the content property of the AdapterPopulatedModelArray... SOMETHING LIKE:
arrayDidChange:function(arr, start, removeCount, addCount){
if (addCount == 0) {return;} //only care about adds right now... not removes...
arr.slice(start, start+addCount).forEach(function(item) {
//push clientId of this item into AdapterPopulatedModelArray content list
self.getPath('list.content').pushObject(item.get('clientId'));
});
}
what I can say is: "its working for me" :) will it break on the next ember-data update? totally possible
For those still struggling with this, you can get yourself a dynamic DS.FilteredArray instead of a static DS.AdapterPopulatedRecordArray by using the store.filter method. It takes 3 parameters: type, query and finally a filter callback.
loadMessages: function() {
var self = this,
room_id = App.getPath('current_room.id');
this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
return msg.get('roomId') === room_id;
})
// set content only after promise has resolved
.then(function (messages) {
self.set('content', messages);
});
}
You could also do this in the model hook without the extra clutter, because the model hook will accept a promise directly:
model: function() {
var self = this,
room_id = App.getPath("current_room.id");
return this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
return msg.get('roomId') === room_id;
});
}
My reading of the source (DS.Store.find) shows that what you'd actually be receiving in this instance is an AdapterPopulatedModelArray. A FilteredModelArray would auto-update as you create records. There are passing tests for this behaviour.
As of ember.data 1.13 store.filter was marked for removal, see the following ember blog post.
The feature was made available as a mixin. The GitHub page contains the following note
We recommend that you refactor away from using this addon. Below is a short guide for the three filter use scenarios and how to best refactor each.
Why? Simply put, it's far more performant (and not a memory leak) for you to manage filtering yourself via a specialized computed property tailored specifically for your needs