I'm having a problem to convert the next line from my java code to mongoDB:
{ "field1.array": { $not : /\w*(whatever)\w*/ }}.
I've tried to use this:
Criteria criteria = new Criteria() {
#Override
public DBObject getCriteriaObject() {
return
new BasicDBObject("field1.array",
new BasicDBObject("$not",
Pattern.compile(regexp)));
}
};
Which does not work because that sends the regular expression as $regex function which is not compatible with $not operator.
I've tried to negate my regular expression with this: ^((?!my string).)*$
It does not work neither for my array if I don't specify the array position.
Any ideas?
I guess, you just lack the "equals" for the pattern. Never tried with DBObject, but using filters it works like this:
collection.find(
Filters.not(Filters.eq("myField", Pattern.compile("xyz.*")))
)
Related
This code
criteriaBuilder.literal(LocalDateTime.now().minusDays( (long) root.get("person").get("birthDay").as(Long.class)))
has not compile error but at run time gets this error:
Cannot cast from Expression to int
I tried using String:
criteriaBuilder.literal(LocalDateTime.now().minusDays( Long.parseValue( root.get("person").get("birthDay").toString())))
This also gets error:
ERROR: For input string: "org.hibernate.query.criteria.internal.path.SingularAttributePath#2ed2d35d"; nested exception is java.lang.NumberFormatException: For input string: "org.hibernate.query.criteria.internal.path.SingularAttributePath#2ed2d35d"
In your first error, you are mixing LocalDateTime.now().minusDays with the Expression root.get("person").get("birthDay").as(Long.class), and it is not possible.
The error is not detected at compile time because you are actually casting the Expression root.get("person").get("birthDay").as(Long.class) to long:
(long) root.get("person").get("birthDay").as(Long.class)
So everything is fine for the compiler, but at runtime an error will be raised because an Expression is not a long value.
In your second error you are trying using:
root.get("person").get("birthDay").toString()
As a result of the evaluation of this code you will get a String representation of the JPA criteria path you are defining, org.hibernate.query.criteria.internal.path.SingularAttributePath#2ed2d35d in your use case.
Then, if you compute Long.parseValue of org.hibernate.query.criteria.internal.path.SingularAttributePath#2ed2d35d if will raise an error because org.hibernate.query.criteria.internal.path.SingularAttributePath#2ed2d35d doesn't represent a valid number.
Under the hood, the problem is that you are trying to apply the operation LocalDateTime.now().minusDays to an Expression, but it is not possible, you need to perform the computation in some other suitable way.
It is unclear by your question what you are actually trying to achieve, but the JPA criteria API provides a rich set of builtin expressions you can use as Predicates to deal with dates, such as, assuming root.get("person").get("birthDay") represent a Date like object:
cb.greaterThanOrEqualTo(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.greaterThan(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.lessThanOrEqualTo(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.lessThan(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
You can create your own function using cb.function as well and use that function in your predicates. Consider for that purpose defining a helper method somewhere in your code, for example:
public static Expression<Long> daysBetween(
CriteriaBuilder cb, Expression<LocalDate> startDate, Expression<LocalDate> endDate) {
return cb.function("DAYS_BETWEEN", long.class, startDate, endDate);
}
Where DAYS_BETWEEN is the name, you can choose the one you consider most appropriate, of a database level predefined or user defined function. In Oracle for example it exists per se, but it should be straight forward to implement in other database systems:
create or replace function days_between...
Then, use this helper method in your code. For example, give me the persons that turns years in the following numberOfDaysToTurnYears days:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
ParameterExpression<Integer> numberOfDaysToTurnYears = cb.parameter(Integer.class);
query.where(
cb.lessThan(
// Here you can use LocalDate.now(), because it is actually a pure literal value
daysBetween(cb, root.get("person").get("birthDay"), cb.literal(LocalDate.now())),
numberOfDaysToTurnYears
)
);
List<Person> people = entityManager.createQuery(query)
.setParameter(numberOfDaysToTurnYears, 10)
.getResultList();
I haven't used this, I found the relevant documentation, I think it seems to be available like the following, just to provide a reference, I hope it can help you.
literal(T)
Integer a = 1;
Long b = 2L;
String c = "3";
Expression<Integer> integerParameter = criteriaBuilder.literal(a);
Expression<Long> longParameter = criteriaBuilder.literal(b);
Expression<String> stringParameter = criteriaBuilder.literal(c);
And i found that method minusDays(long) return a LocalDateTime, so i think we should take that like :
LocalDateTime ldt = LocalDateTime.now().minusDays( (long) root.get("person").get("birthDay").as(Long.class));
Expression<LocalDateTime> longParameter = criteriaBuilder.literal(ldt);
As for how to convert LocalDateTime into the data you need, I am currently unclear, because it is not clear what your specific needs are.
I've parsed the Below Json file and retrieve the username value.
"LogInFunctionTest": [
{
"TestCaseID": "Login-TC_02",
"TestScenario": "Negative Case - Login with unregistered username and Password",
"TestData": [
{
"UserName": "usernameX",
"Password": "passwordX"
}
]
Using the below code to retrieve the UserName Value.
def InputJSON = new JsonSlurper().parse(new File(fileName))
def testDataItem = InputJSON.LogInFunctionTest.find { it.TestCaseID == Login-TC_02 }.TestData.UserName
Output - [usernameX]
After this, I want to remove the brackets from the above.
'Remove brackets from arraylist'
testDataItem = testDataItem.substring(1, testDataItem.length() - 1)
I'm getting the below exception
org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.length() is applicable for argument types: () values: []
Possible solutions: last(), last(), init(), init(), get(int), get(int)
Anyone guide us on how to remove the brackets from the output?
testDataItem is a list of UserNames as TestData contains a list
That's why when it's displayed to you, it has [] round it...
If you just want the first one in the list, then you can do:
def testDataItem = InputJSON
.LogInFunctionTest
.find { it.TestCaseID == 'Login-TC_02' }
.TestData
.UserName
.first()
(ie: put a call to first() at the end)
Obviously, if there's two of them, you'll only be getting the first one
You could also get the first one with .UserName[0], but .first() is more descriptive
testDataItem = testDataItem.get(0)
might do the job.
Looks like you're reading a list of Strings, not a String.
Technically you referred to 'TestData' as a List with the brackets above so proper reference should be:
TestData[0].UserName
... or since it's all contained in the 'LogInFunctionTest' List:
LogInFunctionTest[0].TestData[0].UserName
That is if you are not going to loop/iterate through them.
I would like to know a simple method to write this SPARQL query in Java Code:
select ?input
?string
(strlen(?match)/strlen(?string) as ?percent)
where {
values ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
values (?input ?pattern ?replacement) {
("cat" "^x[^cat]*([c]?)[^at]*([a]?)[^t]*([t]?).*$" "$1$2$3")
("Londn" "^x[^Londn]*([L]?)[^ondn]*([o]?)[^ndn]*([n]?)[^dn]*([d]?)[^n]*([n]?).*$" "$1$2$3$4$5")
}
bind( replace( concat('x',?string), ?pattern, ?replacement) as ?match )
}
order by ?pattern desc(?percent)
This code is contained in the discussion To use iSPARQL to compare values using similarity measures.
The purpose of this code is to find the resources similar to a given word on DBPedia.
This method takes into consideration that I know in advance the strings and the length of it. I would like to know how I can write this query in a parameterized method that, regardless of the word and the length of it, it returns to me the similarity measures.
Update: ARQ - Writing Property Functions is now part of the standard Jena documentation.
It looks like you'd enjoy having a syntactic extension to SPARQL that performs the more complex portions of your query. For example:
SELECT ?input ?string ?percent WHERE
{
VALUES ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
VALUES ?input { "cat" "londn" }
?input <urn:ex:fn#matches> (?string ?percent) .
}
ORDER BY DESC(?percent)
In this example, it's assumed that <urn:ex:fn#matches> is a property function that will automatically perform the matching operation and calculate the similarity.
The Jena documentation does a great job explaining how to write a custom filter function,
but (as of 07/08/2014) does little to explain how to implement a custom property function.
I will make the assumption that you can convert your answer into java code for the purpose of calculating string similarity, and focus on the implementation of a property function that can house your code.
Implementing a Property Function
Every property function is associated with a particular Context. This allows you to limit the availability of the function to be global or associated with a particular dataset.
Assuming you have an implementation of PropertyFunctionFactory (shown later), you can register the function as follows:
Registration
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ARQ.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ARQ.getContext(), reg);
The only difference between global and dataset-specific registration is where the Context object comes from:
final Dataset ds = DatasetFactory.createMem();
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ds.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ds.getContext(), reg);
MatchesPropertyFunctionFactory
public class MatchesPropertyFunctionFactory implements PropertyFunctionFactory {
#Override
public PropertyFunction create(final String uri)
{
return new PFuncSimpleAndList()
{
#Override
public QueryIterator execEvaluated(final Binding parent, final Node subject, final Node predicate, final PropFuncArg object, final ExecutionContext execCxt)
{
/* TODO insert your stuff to perform testing. Note that you'll need
* to validate that things like subject/predicate/etc are bound
*/
final boolean nonzeroPercentMatch = true; // XXX example-specific kludge
final Double percent = 0.75; // XXX example-specific kludge
if( nonzeroPercentMatch ) {
final Binding binding =
BindingFactory.binding(parent,
Var.alloc(object.getArg(1)),
NodeFactory.createLiteral(percent.toString(), XSDDatatype.XSDdecimal));
return QueryIterSingleton.create(binding, execCtx);
}
else {
return QueryIterNullIterator.create(execCtx);
}
}
};
}
}
Because the property function that we create takes a list as an argument, we use PFuncSimpleAndList as an abstract implementation. Aside from that, most of the magic that happens inside these property functions is the creation of Bindings, QueryIterators, and performing validation of the input arguments.
Validation/Closing Notes
This should be more than enough to get you going on writing your own property function, if that is where you'd like to house your string-matching logic.
What hasn't been shown is input validation. In this answer, I assume that subject and the first list argument (object.getArg(0)) are bound (Node.isConcrete()), and that the second list argument (object.getArg(1)) is not (Node.isVariable()). If your method isn't called in this manner, things would explode. Hardening the method (putting many if-else blocks with condition checks) or supporting alternative use-cases (ie: looking up values for object.getArg(0) if it is a variable) are left to the reader (because it's tedious to demonstrate, easily testable, and readily apparent during implementation).
I want to make SQL look like:
select b from Book b order by rand()
how convert that query to Querydsl query?
Is it not supported by Querydsl?
If you know the way to support this query, please answer it..;
thank you.
Querydsl SQL supports it via
NumberExpression.random()
So your query could be expressed like this
query.from(b)
.orderBy(NumberExpression.random().asc())
.list(b);
I am not sure how well it is supported for JPQL, it doesn't seem to be in the standard.
A addition to Timo's answer.
If you use mysql you will get the error "ERROR: FUNCTION schema.random does not exist", this is because mysql has a RAND function instead of a RANDOM function. To fix this you can either add the random function in sql, like this:
DROP FUNCTION IF EXISTS RANDOM;
DELIMITER $$
CREATE FUNCTION RANDOM ()
RETURNS DECIMAL(15,15)
DETERMINISTIC
BEGIN
DECLARE dist DECIMAL(15,15);
SET dist = RAND();
RETURN dist;
END$$
DELIMITER ;
Or fix the random function to use rand with:
public class MySQLJPATemplates extends JPQLTemplates {
public static final MySQLJPATemplates DEFAULT = new MySQLJPATemplates();
public MySQLJPATemplates() {
this(DEFAULT_ESCAPE);
add(Ops.MathOps.RANDOM, "rand()");
add(Ops.MathOps.RANDOM2, "rand({0})");
}
public MySQLJPATemplates(char escape) {
super(escape);
}
}
And use the template as follows:
JPAQuery<Route> query = new JPAQuery<Route>(em, MySQLJPATemplates.DEFAULT);
query.from(b)
.orderBy(NumberExpression.random().asc())
.list(b);
I have a Java app that is hitting a 3rd party RESTful web service that is returning the following JSON:
{"fizz":
{"widgets":
[
{
"widget_id":"295874"
},
{
"widget_id":"295873"
},
{
"widget_id":"295872"
}
],
"otime":1361993756
},
"resp":"ok"
}
Normally I would use GSON or Genson to map this back to a Java POJO, but this is the only area of the code where I have to do this and I want to be lazy here ;-).
I'm trying to come up with a nifty method that extracts the 3 widget_id values (, and `) and returns them as aList`:
public List<Long> extractIdsFromJson(String json) {
// Can I solve this with a regex perhaps?
}
Not sure what the right approach is - regex, replaceAll, something else? Thanks in advance.
Being lazy here will just bite you in the long run. Parse the JSON and extract the values that way; the 'effort' involved will be less, the code will be more understandable, and future code maintainers will not curse your name.
// untested
public List<Long> extractIdsFromJson(String json) {
List<Long> list = new ArrayList<Long>();
Matcher matcher = Pattern.compile("\"widget_id\":\"?(\\d+)\"?").matcher(json);
while (matcher.find())
list.add(Long.valueOf(matcher.group(1)));
return list;
}
If you like being lazy. Here is the solution. I hope you know whatever entails your choice of solving the problem with regex:
It doesn't check for the structure of the JSON. You ignore the fact that the JSON may be malformed and just blindly extract the data.
It works here since you want a property whose value is not an Object or Array.
RAW regex:
"widget_id"\s*:\s*"(\d+)"
In literal string:
"\"widget_id\"\\s*:\\s*\"(\\d+)\""
Use the regex above with Matcher loop:
Pattern p = Pattern.compile("\"widget_id\"\\s*:\\s*\"(\\d+)\"");
Matcher m = p.matcher(inputString);
while (m.find()) {
System.out.println(m.group(1));
}