pagination in cassandra based web application - spring-mvc

How can i do a pagination in cassandra based web application. I am using spring MVC on server side and jquery on client side. I tried this but was not sutisfied.
My row key is UUIDType and every time i am sending the start key as string from client browser so dont know how to convert it back to UUID. A simple example will be appriciated.

Spring-data has this functionality pre-rolled :
http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/repositories.html#web-pagination

If you use PlayOrm for cassandra it returns a cursor when you query and as your first page reads in the first 20 results and displays it, the next page can just use the same cursor in your session and it picks up right where it left off without rescanning the first 20 rows again.
Dean

I would suggest generic solution which shall work for any language. I used python pycassa to work this out:
First approach:
-Say if column_count = 10 (How many results to display on front end)
-collect first 11 rows, sort first 10, send it to user (front end) as JSON object and also parameter last=11th_column
-User then calls for page 2, with prev = 1st_column_id, column_start=11th_column and column_count = 10. Based on this, I query cassandra like cf.get('cf', key, column_start=11th_column, column_count=10)
-This way, I can traverse, next page and previous page.
-Only issue with this approach is, I don't have all columns in super column sorted. So this did not work.
Second approach ( I used in production ):
-fetch all super columns and columns for a row key. e.g in python pycassa, cf.get('cf',key)
-Sort this in python using sorted and lambda function based on column values.
-Once sorted, prepare buckets and each bucked size is of page size/column count. Also filter out any rogue data if needed before bucketing.
-Store page by page results in Redis with keys such as 'row_key|page_1|super_column' and keep refreshing redis periodically.
My second approach worked pretty good with small/medium amount of data.

Related

MS Project: How to set daily actual work for a task using a JavaScript Add-In?

I want to synchronize data for actual work from a web-based application of my company with MS Project. I am currently developing an Add-In with JavaScript in order to achieve this:
The red circle in my screenshot shows the data that I want to set programmatically. However, I have no idea how to achieve this.
I understand that I can get Task GUIDs and then set task fields using the task GUID and the field ID. This way I can save the cumulative actual work, but not per day like in my screenshot.
The API Docs on the MS Office Website are rather hard to read and navigate. Any help would be apprechiated!
Let's first separate the language from the operation.
Operationally, based on your circle, you want to set work for a task to happen on individual days? This is done using timeScaleData, see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2003/aa206255(v=office.11) . When I did something similar (in VBA), I had to (1) get an array of time scale values, then (2) walk/iterate through that array and set work to those days:
set timeScaleValsArry = myTask.Assignments(1).TimeScaleData(startDay, endDay, pjAssignmentTimeScaledWork, daily)
for a = 1 to timeScaleValsArry.Count
timeScaleValsArry[a].value = hoursToWorkThatDay
next
Breaking down the elements above:
myTask is the task (of type task) I want to manipulate.
Assignments is an array representing each resource assigned to the task; for my purposes, I only ever had 1 resource assigned, hence the index of (1).
TimeScaleData is the function that returns the the array starting on the day startDay (whatever you want that to be), endDay, pjAssignmentTimeScaledWork which tells this function what data we want to work with (being work, but there are alternates ), and daily which is the frequency you want to work with (for instance you can go down to minutes, or up to years).
Then the returned array timeScaleValsArry is walked, and inside the loop the daily assignment for each value is manipulated. You'd need to customize this part to meet your needs; alternatively, you don't even need to loop if you always had three days: just hard code the array indices.
As far as language, clearly this is do-able in VBA. Doing this in C# as a VSTO addin has very similar syntax. I'd presume for JavaScript (what are you using, ScriptLab?) would also have similar syntax.

Function of Rows, Rowsets in PeopleCode

I'm trying to get a better understanding of what Rows and Rowsets are used for in PeopleCode? I've read through PeopleBooks and still don't feel like I have a good understanding. I'm looking to get more understanding of these as it pertains to Application Engine programs. Perhaps walking through an example may help. Here are some specific questions I have:
I understand that Rowsets, Row, Record, and Field are used to access component buffer data, but is this still the case for stand alone Application Engine programs run via Process Scheduler?
What would be the need or advantage to using these as opposed to using SQL objects/functions (CreateSQL, SQLExec, etc...)? I often see in AE programs where the CreateRowset object is instantiated and uses a .Fill method with a SQL WHERE Clause and I don't quite understand why a SQL was not used instead.
I've seen in PeopleBooks that a Row object in a component scroll is a row, how does a component scroll relate to the row? I've seen references to rows having different scroll levels, is this just a way of grouping and nesting related data?
After you have instantiated the CreateRowset object, what are typical uses of it in the program afterwards? How would you perform logic (If, Then, Else, etc..) on data retrieved by the rowset, or use it to update data?
I appreciate any insight you can share.
You can still use Rowsets, Rows, Records and fields in stand alone Application Engines. Application Engines do not have component buffer data as they are not running within the context of a component. Therefore to use these items you need to populate them using built-in methods like .fill() on a rowset, or .selectByKey() on a record.
The advantage of using rowsets over SQL is that it makes the CRUD easier. There are built-in methods for selecting, updating, inserting and deleting. Additionally you don't have to worry about making a large number of variables if there were multiple fields like you would with a SQL object. Another advantage is when you do the fill, the data is read into memory, where if you looped through the SQL, the SQL cursor would be open longer. The rowset, row, record and field objects also have a lot of other useful methods such as allowing you to executeEdits (validation) or copy from one rowset\row\record to another.
This question is a bit less clear to me but I'll try and explain. If you have a Page, it would have a level 0 row. It then could have multiple Level 1 rowsets. Under each of those it could have a level 2 rowsets.
Level0
/ \
Level1 Level1
/ \ / \
Level2 Level2 Level2 Level2
If one of your level1 rows had 3 rows, then you would find 3 rows in the Rowset associated with that level1. Not sure I explained this to answer what you need, please clarify if I can provide more info
Typically after I create a rowset, I would loop through it. Access the record on each row, do some processing with it. In the example below, I look through all locked accounts and prefix their description with LOCKED and then updated the database.
.
Local boolean &updateResult;
local integer &i;
local record &lockedAccount;
Local rowset &lockedAccounts;
&lockedAccounts = CreateRowset(RECORD.PSOPRDEFN);
&lockedAccounts.fill("WHERE acctlock = 1");
for &i = 1 to &lockedAccounts.ActiveRowCount
&lockedAccount = &lockedAccounts(&i).PSOPRDEFN;
if left(&lockedAccount.OPRDEFNDESCR.value,6) <> "LOCKED" then
&lockedAccount.OPRDEFNDESCR.value = "LOCKED " | &lockedAccount.OPRDEFNDESCR.value;
&updateResult = &lockedAccount.update();
if not &updateResult then
/* Error handle failed update */
end-if;
end-if;
End-for;

Extracting table from a webpage in automation anywhere

Is there a way to extract a table from a web page in Automation Anywhere after taking certain steps using web recorder. The table does not appear directly, it appears after clicking few controls after launching the URL.
The table that I want to extract is coming after loggin in to the website and filtering using a control for search criteria.
I used web recorder to login and putting the desired search criteria in a text field and I want to extract the table now. When I use web recorder, it launches the URL again and takes me back to the login page which I dont want. I want the bot to stay on the page. Pls help.
Also, what is the significance of session name of an extracted table?
If you clicked on Advanced View, you will find at Step 5 : to run this command using an existing IE window. Try to write the URL of the page with the table and not the one of the login page.
The extracted table is to be used using variable $Table Column(Index)$ with index being the column number or column name
you can export directly using object cloning and in the selection criteria export to csv file. But we need to click on html inner text also in search criteria
An old question, but my experience has been the Extract Data/Table commands are rather poor. Not only do they only work in IE, you cannot call them as commands, they have to be called via a web recording.
Instead, I've found it much more useful to object clone the initial element, grab the DOMXPath, and variablize that. Then throw it into a loop while command and set the condition on finding at least one element (of the elements for the table you are trying to build). You can grab all sorts of useful info in the object clone command and then right that to a variable/table.
For example
//div[#id='updatable-standings']/div[1]/div[1]/div[2]/div[1]/table[1]/tbody[1]/tr[3]/td[2]/div[1]/span[2]
//div[#id='updatable-standings']/div[1]/div[1]/div[2]/div[1]/table[1]/tbody[1]/tr[4]/td[2]/div[1]/span[2]
I can create a incremental variable for {tr[3]} and call it $vTeamLoop$ and change my DOMXPath value in the Object Clone to be
//div[#id='updatable-standings']/div[1]/div[1]/div[2]/div[1]/table[1]/tbody[1]/tr[$vTeamLoop$]/td[2]/div[1]/span[2]
Ultimately, it is more steps than the Data/Table Extract command, but it is far less limited in scope.
Hope that helps.
enter code here

How to use cursors for navigating to previous pages using GQL and the new gcloud-java API?

I'm using the new gcloud-java API (https://github.com/GoogleCloudPlatform/gcloud-java/tree/master/gcloud-java-datastore/src/main/java/com/google/cloud/datastore) for working with the Cloud Datastore. My specific question is on using GQL for pagination with cursors. I was able to page through the results one page at a time in the forward direction using cursors, but not having any luck with paging backwards.
Example Scenario:
Let's say I've 20 entities in a Kind with IDs 1 through 20. I have a page size of 5. Once I'm on the 3rd page (IDs 11 through 15), if I need to go one page back; i.e. retrieve IDs 6 through 10, what would be the correct GQL/sample code? Again, I prefer not to use offset with a number, but would like to use Cursors.
From what I can tell (actually tested), it looks like one needs to keep track of Start/End cursors for each page as they navigate in the forward direction, then use the saved cursors when there is a need to go back. I just want to make sure if this is the correct/only way or there is a simpler way to accomplish this.
Thanks in advance for your help.
If you add to your original query a sort by key (appended to the end of your "order by" clause), you should be able to reverse each property's sort order and use the latest cursor from your original query to get results in reverse.
Suppose you've iterated through some of the values from your forward query's QueryResults. You can call QueryResults's cursorAfter() method, which will return a cursor pointing right after the last result you saw from your original query. Now you can issue a new query (with the opposite sort order on each property, including the key property) using that cursor as the start cursor. You'll probably want to skip the first result, since it will be the last result you saw from the original query.

Access 2010 Query with Parameter and Sort

I have a problem that I've been going round and round with in Access 2010. Imagine a table with these columns:
Name Date Time
Now, I have a query that asks the user to input a begin date and an end date and returns all records that are between those two dates. This works fine. However, as soon as I add a sort to the Date column things go awry. Once you put a sort on a column with a parameter the user gets asked to enter the parameter twice. From what I've been able to find out this is normal (although annoying) behavior in Access.
If I add the Date column in a second time and show the column with the sort and don't show the column with the parameter it works fine. The query would look something like:
Name Date (shown & sorted) Date (not shown & parameters) Time
Now when I run the query it all works well and comes out the way I want it to. This would obviously be a great solution then. However, there's another problem. When I save the query, leave, and reopen the query the two columns are merged back into each other. Thus, the change is lost and the user again sees two inputs.
My question is this: what can I do differently to achieve the desired results?
Some possible things I've thought about but don't know the answer to are:
Is there a way to make it so the columns don't merge? Do I have to use a form with the input boxes and take the data from that (I'd prefer not to do that as it will require a lot of additional work to handle the various things I am doing in the database). Is there some obvious thing I'm missing?
Thanks for any suggestions.
FYI: Here is the SQL from the query
SELECT Intentions.Intention, Intentions.MassDate, Intentions.[Time Requested], Intentions.[Place Requested], Intentions.[Offered By], Intentions.Completed
FROM Intentions
WHERE (((Intentions.MassDate) Between [Enter start date] And [Enter end date]))
ORDER BY Intentions.MassDate, Intentions.[Time Requested];
It is true that sometimes the Query Designer in Access will "reorganize" a query when you save it. However, I don't recall an instance where such a reorganization actually broke anything.
For what it's worth, the following query seems to do what you desire. After saving and re-opening it looks and behaves just the same:
For reference, the SQL behind it is
PARAMETERS startDate DateTime, endDate DateTime;
SELECT NameDateTime.Name, NameDateTime.Date, NameDateTime.Time
FROM NameDateTime
WHERE (((NameDateTime.Date) Between [startDate] And [endDate]))
ORDER BY NameDateTime.Date DESC , NameDateTime.Time DESC;
I have had the same problem and I have discovered the reason:
If, after you have run your query, sort a collumn in the result grid and the say yes to save changes to the query the sort action will be stored with the query. This will actually cause the query to run twice. First to create the result and then one more time to sort. You'll therefore be asked twice for the parameters.
SOLUTION: Run the query (entering your parameters twice ;-) ). Then remove the Sorting by clicking on the AZ-eraser symbol in the task bar above (in the sorting compartment).
Then open your query in design-mode and add the sorting order to the appropriate collumn.
Your are then good to go.
Regards
Jan

Resources