How to use Hibernate Criteria objects for multiple and/or conditions - hibernate-criteria

I need to create a Hibernate criteria restriction that ors 3 Conditions. The problem is that the last condition is acutally to conditions using the AND operator.
My first condition:
Criterion startInRange = Restrictions.between("expectedStartCanonicDate",
rangeStart, rangeEnd);
My second condition:
Criterion endInRange = Restrictions.between("expectedCompletionCanonicDate",
rangeStart, rangeEnd);
MY third condition needs to AND the following two conditions together:
criteria.add(Restrictions.le("expectedStartCanonicDate", rangeStart));
criteria.add(Restrictions.ge("expectedCompletionCanonicDate", rangeEnd));
The restriction I want to do is condition1 or condition2 or condition3. I have found examples that get me close. I can use a LogicalExpression to or the first two conditions together, however, I'm not sure how to or 3 conditions, particularly when the last condition is really two separate conditions 'anded' together.
Any Thoughts?
Fred

A sequence of restrictions linked with or is called a disjunction. A sequence of restrictions linked with and is called a conjunction.
So, what you need is
one conjunction for your third condition
one disjunction to link the first, second, and third conditions:
So here it goes:
Criterion startInRange = Restrictions.between("expectedStartCanonicDate", rangeStart, rangeEnd);
Criterion endInRange = Restrictions.between("expectedCompletionCanonicDate", rangeStart, rangeEnd);
Criterion thirdCondition =
Restrictions.conjunction().add(Restrictions.le("expectedStartCanonicDate", rangeStart))
.add(Restrictions.ge("expectedCompletionCanonicDate", rangeEnd));
Criterion completeCondition =
Restrictions.disjunction().add(startInRange)
.add(endInRange)
.add(thirdCondition);
criteria.add(completeCondition);

Criteria criteriaObj = sessionselectreply.createCriteria(TaskReplyVO.class,"taskreply")
.createAlias("taskreply.objTaskView", "taskview")
.createAlias("objMailTo", "mailto")
.add(Restrictions.eq("taskview.longTaskId", taskid))
.add(Restrictions.eq("mailto.longuserid", userid));

Related

Two conditions in Google Sheets Function

I have a question on using two functions with an if statement in Google Sheets as one complete function. Both variables have to be true, otherwise it returns false. I need one function to check the date 20 months back from today. If said cell is less than today's date 20 months back it's true, naturally. However, for the complete function to return true it also searches for another text value in another cell and has to be an exact match. Both conditions have to be true (the date and the exact match) for the function to be true. So if the date in the cell is less than today's date 20 months back and the text value in the other cell is an exact match, function is true.
Problem is that it seems like the date function does not seem to apply.
=IF(D2<DATE(YEAR(TODAY()),MONTH(TODAY())-20,DAY(TODAY())),AND(REGEXMATCH(M2,"text")),TRUE,FALSE)
You current formula is not set up correctly (nor logically). Given only what you've shown here, this should work:
=IF(AND( D2<DATE(YEAR(TODAY()),MONTH(TODAY())-20,DAY(TODAY())), REGEXMATCH(M2,"text") ),TRUE,FALSE)
Notice that the AND( ) contains both conditions here, whereas your original formula had it only around the second condition.
However, a shorter version of this would be as follows:
=AND( D2<DATE(YEAR(TODAY()),MONTH(TODAY())-20,DAY(TODAY())), REGEXMATCH(M2,"text") )
... since the result of a properly functioning AND( ) is always TRUE or FALSE anyway.
It looks like you're supplying 4 arguments to the IF statement:
=IF(DATECHECK,AND(TEXTCHECK),TRUE,FALSE)
The IF statement expects 3 arguments instead. 1) the condition, 2) the value if true, and 3) the value if false. You can combine your two conditions using an AND statement like this:
AND(DATECHECK,TEXTCHECK)
The final formula would then be:
=IF(AND(D2<DATE(YEAR(TODAY()),MONTH(TODAY())-20,DAY(TODAY())), REGEXMATCH(M2,"text")),TRUE,FALSE)

Combine two nested IF statements with multiple criteria

I have two columns of data in "Meds" sheet...
MedContinuing AgeAtMedStop
Yes "Blank"
Yes 72.22
No "Blank"
No 72.57
"Blank" 73.85
I am writing a formula in a separate sheet to return 1 or 0 based on the following:
If MedContinuing is "Blank", do nothing
If MedContinuing is "No" and AgeAtMedStop is blank, do nothing
If MedContinuing is "Yes" and AgeAtMedStop is "Blank", return 1. If AgeAtMedStop is a number, return 0.
If MedContinuing is "No" and AgeAtMedStop is a number, return 1. Otherwise, return nothing.
I was able to write two separate functions (see below) for when MedContinuing is "Yes" or when it is "No", but I need to combine both into one formula.
When it's Yes...
=IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No","",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),1,0)))
When it's No...
=IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="Yes","",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),"",
IF(AND(INDEX(Meds!2:2,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!2:2,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),1,0))))
EDIT: Solution
Using Peter K's logic...
=IF(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="","",
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),"",
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))=""),1,
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="Yes",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),0,
IF(AND(INDEX(Meds!6:6,MATCH("MedContinuing",Meds!$1:$1,0))="No",INDEX(Meds!6:6,MATCH("AgeAtMedStop",Meds!$1:$1,0))>0),1,"")))))
It is not entirely clear from your question why you would use INDEX and MATCH functions for such straightforward problem ?
I suggest to start with the basic nested if function :
=IF(A2="";"";IF(A2="No";IF(B2="";"";1);IF(B2="";1;0)))
You can put this function next to your two columns, and then copy to another worksheet, so the references are taken care of by Excel.
I also assume that your data is clean and correct i.e. only the 3 possible values for MedContinuing ("Yes", "No" or blank) and 2 for AgeAtMedStop (blank or a number) exist in your columns, so no IF test is needed to eliminate other possible values.
You can try this method below
I have created a helper table for the logic you require, it will help to update or extend the logic in future
Formula in cell C2 is
=INDEX($F$2:$G$4,MATCH(A2,$E$2:$E$4,0),IF(B2="Blank",1,IF(ISNUMBER(B2),2,0)))

Prolog - Custom 'if-then-else'

I'm experimenting with Prolog and tried to make my own "if-then-else" method, so that I don't use the -> ; method, for experimenting's sake.
My goal is to make it so that there can be nested ifs and elses in my code if required.
Thus far I have got this:
ifthenelse(_, G, G):- G. %no matter the condition, the goals are the same
ifthenelse(true,G,_):- G. %if
ifthenelse(false,_,G):- G. %else
I think my way hardly seems correct. How can I make my own ifthenelse/3 properly?
Thank you
Preface: What you have implemented is, in an important way, a lot better than the built-in construct you mentioned. I will discuss this point in more detail below.
Regarding the literal question: I think you are quite close already, since you can already nest this to some extent:
?- ifthenelse(C1, ifthenelse(C2,X=1,X=2), X=3).
C1 = C2, C2 = true,
X = 1 ;
C1 = true,
C2 = false,
X = 2 ;
C1 = false,
X = 3.
What now remains is to make it nestable in the condition. For this, you need a way to reify the outcome of conditions, that is, to turn the truth value into a Prolog term that you can reason about symbolically.
See if_/3 for more information: Indexing dif/2
A key property this construct preserves is called logical-purity. In particular, do not erroneously commit to one branch if both are logically possible!
Note on purity: From a declarative point of view, what you have implemented is very nice and has a clear logical interpretation. Taking for example the last two clauses, we can read ifthenelse(C,G1,G2) as: If C is true, then the predicate holds if G1 holds. If C is false, then it holds if G2 holds. Perfectly fine. A semantic "if...then" is not in any way problematic; in fact, every single Horn clause can be read in this way, as an implication from right to left.
In contrast, the built-in construct you mention lacks such a declarative reading in general. For example:
?- ( ( X = 1 ; X = 2 ) -> true ; true ).
X = 1.
But on the other hand:
?- X = 2, ( ( X = 1 ; X = 2 ) -> true ; true ).
X = 2.
So adding a constraint has led to a new solution. A classical logician's nightmare.
Your construct avoids such problems, because it does not prematurely commit to any particular branch. This yields a much more versatile predicate that can also be used in other directions. For example, see that all possible solutions are correctly generated:
?- ifthenelse(C, true, true).
true ;
C = true ;
C = false.
So, I highly encourage your way of formulating this: As you have made perfectly clear, it's your own 'if-then-else', and you are using only pure monotonic constructs to express it.
On a psychological note, I generally prefer to give more room to pure declarative constructs and I added this section only because the comments expressed genuine interest in these aspects.
It is known that in order to avoid -> and implement it yourself, you need to use cut (!) to simulate same behavior:
if_then_else(P, Q, R) :- P, !, Q.
if_then_else(P, Q, R) :- R.
where P is the condition Q the then part and R the else part.

SPARQL: combine and exclude regex filters

I want to filter my SPARQL query for specific keywords while at the same time excluding other keywords. I thought this may be easily accomplished with FILTER (regex(str(?var),"includedKeyword","i") && !regex(str(?var),"excludedKeyword","i")). It works without the "!" condition, but not with. I also separated the FILTER statements, but no use.
I used this query on http://europeana.ontotext.com/ :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX edm: <http://www.europeana.eu/schemas/edm/>
PREFIX ore: <http://www.openarchives.org/ore/terms/>
SELECT DISTINCT ?CHO
WHERE {
?proxy dc:subject ?subject .
FILTER ( regex(str(?subject),"gemälde","i") && !regex(str(?subject),"Fotografie","i") )
?proxy edm:type "IMAGE" .
?proxy ore:proxyFor ?CHO.
?agg edm:aggregatedCHO ?CHO; edm:country "germany".
}
But I always get the result on the first row with the title "Gemäldegalerie", which has a dc:subject of "Fotografie" (the one I want excluded). I think the problem lies in the fact that one object from the Europeana database can have more than one dc:subject property, so maybe it looks only for one of these properties while ignoring the other ones.
Any ideas? Would be very thankful!
The problem is that your combined filter checks for the same binding of ?subject. So it succeeds if at least one value of ?subject matches both conditions (which is almost always true, because the string "Gemäldegalerie", for example, matches your first regex and does not match the second).
So for the negative condition, you need to formulate something that checks for all possible values, rather than just one particular value. You can do this using SPARQL's NOT EXISTS function, for example like this:
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX edm: <http://www.europeana.eu/schemas/edm/>
PREFIX ore: <http://www.openarchives.org/ore/terms/>
SELECT DISTINCT ?CHO
WHERE {
?proxy edm:type "IMAGE" .
?proxy ore:proxyFor ?CHO.
?agg edm:aggregatedCHO ?CHO; edm:country "germany".
?proxy dc:subject ?subject .
FILTER(regex(str(?subject),"gemälde","i"))
FILTER NOT EXISTS {
?proxy dc:subject ?otherSubject.
FILTER(regex(str(?otherSubject),"Fotografie","i"))
}
}
As an aside: since you are doing regular expression checks, and now combining them with an NOT EXISTS operator, this is likely to become very expensive for the query processor quite quickly. You may want to think about alternative ways to formulate your query (for example, using the exact subject string to include or exclude to eliminate the regex), or even having a look at some non-standard extensions that the SPARQL endpoint might provide (OWLIM, for example, the store on which the Europeana endpoint runs, supports various full-text-search extensions, though I am not sure they are enabled in the Europeana endpoint).

How Lucene scores results in a RegexQuery?

I can see how two values, when doing a regular/fuzzy full text search, can be compared to determine which one is "better" (i.e. one value contains more keywords than the other, one contains less non-keywords than the other).
However, how Lucene computes the score when doing regex queries using RegexQuery? It is a boolean query - a field's value is either compatible with the regex or not. Lucene can't take keywords from my regex query and do its usual magic...
There are two passes. In the first, it generates a list of all terms which match the regex. In the second, it finds all documents with terms matching that regex.
The major code you want to look at is in MultiTermQuery:
public Query rewrite(IndexReader reader) throws IOException {
FilteredTermEnum enumerator = getEnum(reader);
BooleanQuery query = new BooleanQuery();
try {
do {
Term t = enumerator.term();
if (t != null) {
TermQuery tq = new TermQuery(t); // found a match
tq.setBoost(getBoost() * enumerator.difference()); // set the boost
query.add(tq, false, false); // add to query
}
} while (enumerator.next());
} finally {
enumerator.close();
}
return query;
}
Two things:
The boolean query is instantiated with coord on. So the standard coord scoring applies (i.e. the more terms you get, the better).
The boost of the term query is given by enumerator.difference(). However, as of 3.0.1 this just returns 1:
#Override
public final float difference() {
// TODO: adjust difference based on distance of searchTerm.text() and term().text()
return 1.0f;
}
So at some point this will return the distance (probably levenstein) between the terms. But for now it does nothing.
This is just a wild guess, but one possible metric could be the number of backtracking steps the regex engine needs to take to match your search strings.
Of course, these values also depend mightily on the quality of your regex, but when comparing several matches, the one that was "easier to match" could be considered a better match than the one that the regex engine had to go through contortions for.