criteria query is not getting data when adding or condition - java

I have a Java file that query data and I'm trying to add a filtering function. By using criteria builder and criteria query, I manage to get data that I want to filter.
As starter, this is the column to display my data:
Name Host
Fikrie ubuntu
Fikrie2 unix
Fikrie3 ulalala
Fikrie4 ugagaga
There are 3 variable used here. The Name column, is displaying data from name. For the Host column, it is a bit tricky. It will display the hostname, but if there is a logAsHost display, this data will overwrite the hostname.
So this is how my data really look like:
Name Host
Fikrie ubuntu <-- hostname = 1, logAsHost = ubuntu
Fikrie2 unix <-- hostname = 123, logAsHost = unix
Fikrie3 ulala <-- hostname = ulala, logAsHost = no value
Fikrie4 ugaga <-- hostname = ugaga, logAsHost = no value
When I try to filter just 1 variable, I manage to do so. (Eg. filter by Name). When I try to filter out 2 variable, then a problem happen. I didnt manage to get any data.
This is the code that I use:
public List<Connection> retrieveAll(String nameFilter, String hostFilter,
int start, int length) {
ServiceUtil.requireAdmin();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Connection> q = cb.createQuery(Connection.class);
Root<Connection> c = q.from(Connection.class);
q.select(c);
logger.info("nameFilter = [" + nameFilter + "]");
logger.info("hostFilter = [" + hostFilter + "]");
//This is the line that I use to query data.
//when I replace Connection_.hostname with Connection_.logAsHost, or Connection_.name
//It works just fine. So I use either one of these line to query.
//q.where(cb.like(c.get(Connection_.hostname), "%" + hostFilter + "%"));
//q.where(cb.like(c.get(Connection_.logAsHost), "%" + hostFilter + "%"));
//q.where(cb.like(c.get(Connection_.name), "%" + nameFilter + "%"));
//This is the problem part.
//When I add cb.or, it cannot get any data.
//From the documentation, it should just be q.where(cb.or(A, B))
//Where A is the first expression and B is the second.
// I have confirm both the expression are working by calling it separately
q.where(cb.or(cb.like(c.get(Connection_.hostname), "%" + hostFilter + "%")), cb.like(c.get(Connection_.logAsHost), "%" + hostFilter + "%"));
List<Connection> results = em.createQuery(q).setFirstResult(start)
.setMaxResults(length).getResultList();
for (Connection conn : results) {
logger.info("Name=" + conn.getName() + ", hostname=["
+ conn.getHostname() + "]" + ", logAsHost =["
+ conn.getLogAsHost() + "]");
}
return results;
}
This the log to show that the data is available or not:
I used c.get(Connection_.hostname), and passed u to hostFilter,
INFO nameFilter = []
INFO hostFilter = [u]
INFO Name=fikrie3, hostname=[ulala], logAsHost =[]
INFO Name=testt, hostname=[ugaga], logAsHost =[]
I used c.get(Connection_.logAsHost), and passed u to hostFilter,
INFO nameFilter = []
INFO hostFilter = [u]
INFO Name=fikrie, hostname=[192.168.56.90], logAsHost =[ubuntu]
INFO Name=fikrie2, hostname=[192.168.56.90], logAsHost =[unix]
I combine both and passed u to hostFilter,
INFO nameFilter = []
INFO hostFilter = [u]
I'm assuming the cb.or() is causing this error. If so, how do I use OR condition properly in criteriaquery? I'm following this part
or(Expression<java.lang.Boolean> x, Expression<java.lang.Boolean> y) from the documentation.

For me it looks like only a problem with your parenthesis. Your predicates are not parameter to the or method
you have
q.where(
cb.or(
cb.like(c.get(Connection_.hostname), "%" + hostFilter + "%")
),
cb.like(c.get(Connection_.logAsHost), "%" + hostFilter + "%")
);
Which lead to an AND of both predicates.
It should rather be
q.where(
cb.or(
cb.like(c.get(Connection_.hostname), "%" + hostFilter + "%"),
cb.like(c.get(Connection_.logAsHost), "%" + hostFilter + "%")
)
);

Related

"InvalidMongoDbApiUsageException:

Criteria criteria = new Criteria();
if(StringUtils.isNotEmpty(payeeIdentifier)){
criteria.orOperator(Criteria.where(MAPPING + "." + NPI).is(payeeIdentifier),
Criteria.where(MAPPING + "." + GROUP_NAME).regex(CriteriaBuilder.toRegexAny(payeeIdentifier), CASE_INSENSITIVE),
Criteria.where(MAPPING + "." + PROVIDER_NAME).regex(CriteriaBuilder.toRegexAny(payeeIdentifier), CASE_INSENSITIVE),
Criteria.where(MAPPING + "." + LAST_NAME).regex(CriteriaBuilder.toRegexAny(payeeIdentifier), CASE_INSENSITIVE),
Criteria.where(MAPPING + "." + PROVIDER_FULL_NAME).regex(CriteriaBuilder.toRegexAny(payeeIdentifier), CASE_INSENSITIVE),
Criteria.where(MAPPING + "." + FEIN).is(payeeIdentifier));
}
if(isSNPI){
criteria.orOperator(
Criteria.where(REQUEST_TYPE).is(GROUP).andOperator(Criteria.where(MAPPING + "." + IS_SNPI_ALLOWED).is(true)),
Criteria.where(REQUEST_TYPE).ne(GROUP)
);
}
final Query query = new Query();
query.addCriteria(criteria);
If payeeIdentifier contains identifying data and isSNPI is also true getting this exception :
"InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second '$or' expression specified as '$or : [Document{{requestType=group, $and=[Document{{mapping.isSNPIAllowed=true}}]}}, Document{{requestType=Document{{$ne=group}}}}]'. Criteria already contains '$or : [Document{{mapping.npi=g3}}, Document{{mapping.groupName=.\Qg3\E.}}, Document{{mapping.providerName=.\Qg3\E.}}, Document{{mapping.lastName=.\Qg3\E.}}, Document{{mapping.providerFullName=.\Qg3\E.}}, Document{{mapping.fein=g3}}]'."
}

Array type found error when try to call from an array of string urls

I just have a question in running a Get request based on string urls.
The code below determines the string urls and puts each urls in an array for a table row.
final String URL_CORE = “/test/platform/auth”;
List<String> urls = new ArrayList<>();
rows.forEach(row -> {
final String clientValue = row.getCell("client");
final String uriValue = row.getCell("uri");
final String typeValue = row.getCell("type"));
urls.add(URL_CORE + "?" +
(clientValue.isEmpty ? "" : CLIENT + "=" + clientValue + "&") +
(uriValue.isEmpty ? "" : URI + "=" + uriValue + "&") +
(typeValue.isEmpty ? "" : TYPE + "=" + typeValue);
});
Within the forEach, I have this code where I just want to run the get request for the url string (for each row at a time). It is giving me an erray type expected found and wondering what am I doing wrong?
getRequest(queryParamsList[row]);
It seems by the name that queryParamsList is a List, not an array, so you have to access element by list.get(index) method. If you dont have the index, you can get it by list.indexOf(element)

Read and write to different Mongo collections using Spark with Java

I am a relative newbie to Spark. I need to read from a Mongo collection in Java using Spark, change some field values, let's say I am appending "123" to one field value and write into another collection. Accordingly I had 2 separate Mongo URIs as the input and output URIs configured in Spark. I am then proceeding to read from the input collection. However, what I am not understanding is how would I make the same RDD of documents as output to another collection. This is the input code:
String inputUri = "mongodb://" + kp.getProperty("source.mongo.userid") + ":"
+ Encryptor.decrypt(kp.getProperty("source.mongo.cache")) + "#"
+ kp.getProperty("source.mongo.bootstrap-servers") + "/" + kp.getProperty("source.mongo.database")
+ "." + kp.getProperty("source.mongo.inputCollection") + "?ssl=true&connectTimeoutMS="
+ kp.getProperty("source.mongo.connectTimeoutMS") + "&socketTimeoutMS="
+ kp.getProperty("source.mongo.socketTimeoutMS") + "&maxIdleTimeMS="
+ kp.getProperty("source.mongo.maxIdleTimeMS");
String outputUri = "mongodb://" + kp.getProperty("source.mongo.userid") + ":"
+ Encryptor.decrypt(kp.getProperty("source.mongo.cache")) + "#"
+ kp.getProperty("source.mongo.bootstrap-servers") + "/" + kp.getProperty("source.mongo.database")
+ "." + kp.getProperty("source.mongo.outputCollection") + "?ssl=true&connectTimeoutMS="
+ kp.getProperty("source.mongo.connectTimeoutMS") + "&socketTimeoutMS="
+ kp.getProperty("source.mongo.socketTimeoutMS") + "&maxIdleTimeMS="
+ kp.getProperty("source.mongo.maxIdleTimeMS");
SparkSession spark = SparkSession.builder().master("local[3]").appName(kp.getProperty("spark.app.name"))
.config("spark.mongodb.input.uri", inputUri)
.config("spark.mongodb.output.uri", outputUri)
...;
JavaSparkContext sc = new JavaSparkContext(spark.sparkContext());
JavaMongoRDD<Document> rdd = MongoSpark.load(sc);
System.out.println("Count: " + rdd.count());
System.out.println(rdd.first().toJson());
Please help me in this regard.
I have got the answer myself. I went the Dataset route instead of RDDs which made the modification simpler. So, to load the Mongo colection, I use
Dataset<Row> df = MongoSpark.load(sc).toDF();
Then I create a temporary view upon it in orcder to be able to use Spark SQL:
df.createOrReplaceTempView("Customer");
I register an UDF for operating upon each column value:
spark.udf().register("Test", new TestUDF(), DataTypes.StringType);
the UDF definition is as follows:
public class TestUDF implements UDF1<String, String> {
#Override
public String call(String customer) throws Exception {
return customer + "123";
}
}
Then I call the UDF using the same column name as the original so that the values in the original dataset are replaced:
df = df.withColumn("CustomerName", functions.callUDF("Test", functions.col("CustomerName")));
Then I write it back to Mongo in a separate collection:
MongoSpark.write(df).option("collection", "myCollection").save();

Siddhi (as a libary) many queries for the Same Stream

(I'm jumping from Esper to Siddhi)
I'm trying to deploy several queries in the same stream. The example here https://docs.wso2.com/display/CEP400/Using+Siddhi+as+a+Library shows how to deploy a query in a stream, altogether in one ExecutionPlan. So what if I want to add a query to the same execution plan, o same stream?
I'm interest to do this grammatically, Java code.
UPDATE
I want to add queries in an existing execution plan. This means while streams are arriving, and not before.
Using an example posted as answer:
SiddhiManager siddhiManager = new SiddhiManager();
String executionPlan = "" +
"#Plan:name('demo') " +
"" +
"define stream cseEventStream (symbol string, price float, volume long);" +
"" +
"from cseEventStream[symbol==\"WSO2\"] " +
"insert into wso2Stream;" +
"" +
"from cseEventStream[symbol==\"ABC\"] " +
"insert into abcStream;";
ExecutionPlanRuntime executionPlanRuntime = siddhiManager.createExecutionPlanRuntime(executionPlan);
StreamCallback streamCallback = new StreamCallback() {
#Override
public void receive(Event[] events) {
EventPrinter.print(events);
}
};
executionPlanRuntime.addCallback("wso2Stream", streamCallback);
//Similarly, we can add another call back for abcStream
streamCallback.startProcessing();
InputHandler inputHandler = executionPlanRuntime.getInputHandler("cseEventStream");
executionPlanRuntime.start();
// HERE: ADD new query <---------------------------------------------
inputHandler.send(new Object[]{"WSO2", 700f, 100l});
inputHandler.send(new Object[]{"ABC", 60.5f, 200l});
inputHandler.send(new Object[]{"WSO2", 60.5f, 200l});
streamCallback.stopProcessing();
executionPlanRuntime.shutdown();
Following sample adds multiple Queries, for same Stream (cseEventStream), within the same Execution Plan.
SiddhiManager siddhiManager = new SiddhiManager();
String executionPlan = "" +
"#Plan:name('demo') " +
"" +
"define stream cseEventStream (symbol string, price float, volume long);" +
"" +
"from cseEventStream[symbol==\"WSO2\"] " +
"insert into wso2Stream;" +
"" +
"from cseEventStream[symbol==\"ABC\"] " +
"insert into abcStream;";
ExecutionPlanRuntime executionPlanRuntime = siddhiManager.createExecutionPlanRuntime(executionPlan);
StreamCallback streamCallback = new StreamCallback() {
#Override
public void receive(Event[] events) {
EventPrinter.print(events);
}
};
executionPlanRuntime.addCallback("wso2Stream", streamCallback);
//Similarly, we can add another call back for abcStream
streamCallback.startProcessing();
InputHandler inputHandler = executionPlanRuntime.getInputHandler("cseEventStream");
executionPlanRuntime.start();
inputHandler.send(new Object[]{"WSO2", 700f, 100l});
inputHandler.send(new Object[]{"ABC", 60.5f, 200l});
inputHandler.send(new Object[]{"WSO2", 60.5f, 200l});
streamCallback.stopProcessing();
executionPlanRuntime.shutdown();
I've used Siddhi version 3.0.6-beta2.
This code sample is a modification made to one of the Siddhi Passthrough test cases (PassThroughTest4).
Update:
Looking at ExecutionPlanRuntime class, it does not seem like it is possible to add queries "on the run".
So, to my understanding, you will have to shutdown current execution plan runtime, add those new queries and start it back.

Hibernate query language like operator not working

cmTDsquery = createQuery("from CmTxnDetailStage cstg where cstg.statusCd=:err" +
" and (cstg.id.batchName like :batchname or cstg.id.batchName like :batchname1)"+
" and cstg.prodTypeBlfd like :search1 "+
" and trunc(cstg.tranUploadDttm)=:uploadDt");
cmTDsquery.bindStringProperty("search1", CmTxnDetailStage.properties.prodTypeBlfd, search);
I declared the search parameter as
search = "MON%";
If I replace the :search1 with 'MON%' ,It works fine and query returns result.
Only above code does not work and returns NULL.
Thanks
----------------Edit 1
cmTDsquery.bindStringProperty("batchname",CmTxnDetailStage.properties.batchName,batchNamePattern);
cmTDsquery.bindStringProperty("batchname1",CmTxnDetailStage.properties.batchName,batchNamePattern1);
Sorry to mention this late , but above bindStringProperty methods works like a charm.
batchname and batchname1 contains "CR_STLM_UBROL%" and "%RMB_PINDBT%".
Do like this while setting parameter
"%"+search+"%"
I can't understand exactly the line
cmTDsquery.bindStringProperty("search1", CmTxnDetailStage.properties.prodTypeBlfd, search);
Do you set the correct value - "MON%" and not for example "MON"?
I have used HQL like query.setParameter("search1","MON%") and it worked fine with like operators.
My code is almost the same :
whereClause = whereClause + (whereClause.length() > 0 ? "AND " : "") + "ac.name LIKE :name ";
And further in my code :
if (searchCriteria.getNameSearchOperator() == SQL_STRING_SEARCH_OPERATORS.CONTAINS) {
value = "%" + value + "%";
}
if (searchCriteria.getNameSearchOperator() == SQL_STRING_SEARCH_OPERATORS.START_WITH) {
value = value + "%";
}
query.setParameter("name", value);
Try using setParameter instead of bindStringProperty.

Categories