Migrating from AdWords to GoogleAds api.
Querying search_term_view:
val googleAdsClient: GoogleAdsClient = GoogleAdsClient.newBuilder()
.setCredentials(credential)
.setDeveloperToken(developerToken)
.setLoginCustomerId(loginCustomerId.toLong)
.build()
val svc = googleAdsClient.getLatestVersion.createGoogleAdsServiceClient()
val query = s"""
SELECT
segments.keyword.info.text
,search_term_view.search_term
,segments.date
FROM search_term_view
WHERE segments.date BETWEEN '2022-01-01' AND '2022-01-01'
"""
svc.search(customerId, query).iteratePages().asScala.foreach { page =>
page.iterateAll().asScala.foreach { row =>
//row processing
}
}
The issue is that svc.search() skips rows, if one of columns is null.
So getting results like
text1,term1
text2,term2
While same request to Adwords api returns results like
text1,term1
text2,term2
--,term3
Haven't found anything about nulls ignoring in docs.
Using latest google ads v10 lib:
"com.google.api-ads" % "google-ads" % "17.0.1"
Received response from google team:
"Using segments fields in your query may result in fewer records being returned. This behavior is further explained in this section of our segmentation guide. If no values can be associated to the segments field that is included in the SELECT clause, then no records will also be returned for it.
In addition, zero metrics records may also not be returned when segments fields are used as per this other guide."
I have a CellTable with Pagination that is fed by a ListDataProvider. I set the page size to 5 and the expectation is that when there are more than multiples of 5 rows in ListDataProvider, the page numbers get incremented, and vice-versa. I have Add and Delete buttons that can be used to add and delete cell rows.
The problem is that Pagination adds and deletes pages at the wrong ListDataProvider size. For example, since the page size is 5, I'm expecting that when I add the 6th row to the table, the page size gets incremented. However, the page size is being incremented when the 7th row is added instead of the 6th.
Page not incremented with 6th entry -
Page incremented with 7th entry -
The issue is the same when deleting entries too. The page is updated when row size is down to 4 instead of 5. The issue does not persist if I refresh the page though. As in, when I add the 6th entry and refresh the page, the page number gets incremented as expected, and vice-versa when deleting.
I tried debugging this but couldn't figure out why this is happening. What am I doing wrong here? My code -
#UiField(provided=true) CellTable<MyClass> myTable = new CellTable<MyClass>();
final ListDataProvider<MyClass> myProvider = new ListDataProvider<MyClass>();
final SingleSelectionModel<MyClass> selectionModel = new SingleSelectionModel<MyClass>();
#UiField(provided=true) Pagination pagination = new Pagination(PaginationSize.SMALL);
SimplePager pager;
myProvider.addDataDisplay(myTable);
// create and add columns
createPagination();
private void createPagination() {
myTable.setSelectionModel(selectionModel);
pager = new SimplePager(TextLocation.CENTER, ((SimplePager.Resources)GWT.create(SimplePager.Resources.class)), false, 0, false);
pager.setRangeLimited(false);
pager.setDisplay(myTable);
pager.setPageSize(5);
pagination.rebuild(pager);
}
I'm also calling the createPagination() method in the onSuccess() methods for the add and delete functions.
The .ui.xml for the CellTable and Pagination -
<bc:CellTable ui:field="myTable" striped="true" bordered="true" width="800px" styleName="{style.myTableStyle}"/>
<b:Pagination ui:field="pagination" />
Adam's comment helped me debug the issue.
After adding or removing data, I needed to flush the ListDataProvider so that the changes take place immediately instead of waiting until the end of the event loop -
myProvider.flush();
I have:
a database table with 400 000 000 rows (Cassandra 3)
a list of circa 10 000 keywords
both data sets are expected to grow in time
I need to:
check if a specified column contains a keyword
sum how many rows contained the keyword in the column
Which approach should I choose?
Approach 1 (Secondary index):
Create secondary SASI index on the table
Find matches for given keyword "on fly" anytime
However, I am afraid of
cappacity problem - secondary indices can consume extra space and for such large table it could be too much
performance - I am not sure if finding of keyword among hundreds milions of rows can be achieved in a reasonable time
Approach 2 (Java job - brute force):
Java job that continuously iterates over data
Matches are saved into cache
Cache is updated during the next iteration
// Paginate throuh data...
String page = null;
do {
PagingState state = page == null ? null : PagingState.fromString(page);
PagedResult<DataRow> res = getDataPaged(query, status, PAGE_SIZE, state);
// Iterate through the current page ...
for (DataRow row : res.getResult()) {
// Skip empty titles
if (row.getTitle().length() == 0) {
continue;
}
// Find match in title
for (String k : keywords) {
if (k.length() > row.getTitle().length()) {
continue;
}
if (row.getTitle().toLowerCase().contains(k.toLowerCase()) {
// TODO: SAVE match
break;
}
}
}
status = res.getResult();
page = res.getPage();
// TODO: Wait here to reduce DB load
} while (page != null);
Problems
It could be very slow to iterate through whole table. If I waited for one second per every 1000 rows, then this cycle would finish in 4.6 days
This would require extra space for cache; moreover, frequent deletions from cache would produce tombstones in Cassandra
A better way will be to use a search engine like SolR our ElasticSearch. Full text search is their speciality. You could easily dump your data from cassandra to Elasticsearch and implement your java job on top of ElasticSearch.
EDIT:
With Cassandra you can request your result query as a JSON and Elasticsearch 'speak' only in JSON so you will be able to transfer your data very easily.
Elasticsearch
SolR
This is the document structure which in my bucket.
{
"_class": "com.link.pojo.Event",
"year": "2015",
"start": 1440115200000,
"name": "129811",
"domain": "5000$3$2015$Exhibition",
"sporttype": "Indoor",
"eventtype": "Exhibition",
"end": 1440151199000,
}
In here start mean event start date and the type is util Date. Example date format value is 2015-08-10T09:45:00.000+0000
Now I want to fetch all the documents start in current date using couchbase view. This is the way I'm trying to get it, What are the
// Create the CouchbaseClient Query object & Pass the time range to fetch events.
Query query = new Query();
// Filter on the start date and this value has to be within below given range params.
query.setIncludeDocs(true);
query.setDescending(true);
query.setInclusiveEnd(true);
query.setRange(ComplexKey.of(""), ComplexKey.of(""));
List<Event> eventList = `eventService.getEventsByCurrentDate(query);`
What are the values I should have to pass within query.setRange(); function. And what is the view I need to implement?
function (doc, meta) {
if (doc._class == "com.link.pojo.Event") {
emit(doc.start, null);
}
}
You're doing it wrong :]
A query is just a way to filter some of the results of a view. So start by defining a view - and then work out which query you need to use to get just what you need.
start by creating the view in Couchbase UI.
then look at the results of the view - again using couchbase UI. There should be a link you can click to see the results of the view in a new tab of your browser.
You can then edit the url to "query" the results of your view. add "&key=123 to get just that key. SetRange just means - "get the keys that fall in that range of numbers".
in your case, since your view emits the "start" field, your keys (or range) will have to be in the same format. So something like &key=1440115200000
I hope this helps.
I have developed code as below.
jQuery(document).ready(function(){
jQuery("#records").jqGrid({
height:350,
datatype: 'local',
colNames:['Policy Name','Policy Type', 'Time allowed (HH:mm)','Expiration Duration (days)','Session Pulse(minutes)','Description'],
colModel :[
{name:'pName', index:'pName', editable:true,sorttype:'text',width:150,editoptions:{size:10},formatter:'showlink',formatoptions:{baseLinkUrl:'javascript:' , showAction: "GetAndShowUserData(jQuery('#list2'),'",addParam: "');"}},
{name:'pType', index:'pType', sorttype:'text',editable:true,width:150,editoptions:{size:10}},
{name:'timeAllowed', index:'timeAllowed', sorttype:'text',editable:true,width:200, align:"right",editoptions:{size:10}},
{name:'expDuration', index:'expDuration', sorttype:'text',editable:true,width:200, align:"right",editoptions:{size:10}},
{name:'sessionPulse', index:'sessionPulse',sorttype:'int',editable:true,width:200, align:"right",editoptions:{size:10}},
{name:'description', index:'description', sortable:false,editable:true,width:200,editoptions:{size:10}}],
pager:jQuery('#pager'),
rowNum:10,
sortname: 'pName',
autowidth:true,
altRows:true,
drag:true,
sortorder: "asc",
rowList:[2,5,10,20],
viewrecords: true,
loadonce:false,
multiselect: true,
/*
onSelectRow: function(id){
var gr = jQuery("#records").jqGrid('getGridParam','selrow');
if( gr != null ) jQuery("#records").jqGrid('editGridRow',gr,{height:280,reloadAfterSubmit:false});
else alert("Please Select Row");
},
editurl: "server.php",
*/
caption:'Manage Policy'
});
});
Now, I want to make an Ajax request to the servlet for next records when the user presses >> the (next) button of the jqGrid. I have searched much on the Internet, but I found a lot of PHP code, but I can not understand that PHP; I want to develop that thing in Java. How can I do that?
As GPS said, the paging in jqGrid works by paging through its current dataset. You have to load a big set of data, and it will page through that dataset. There may be a way to get it to behave the way you want, but I don't know how.
For my grids, I use the pagination plugin to trigger an Ajax call to get the next page of data. When the data comes back, I just clear the grid (clearGridData) and add the new set of data using addRowData.
I'm a .NET programmer, so I don't know how you'd do the database calls in with Java, but that's not really a jqGrid question.
To determine how many pages there are, you take the count of all the records that you'll be paging through and divide that by the number of records you will show on the grid per page.