Is there a way in drools to check for a set of conditions, rather than a pair of conditions? What I mean by this is let's say I have a fact type called Ticket, and I've inserted two Ticket facts with the same owner field; how do I prevent the following rule from firing twice? (once where A=$t1,B=$t2, and once where B=$t1,A=$t2)
rule "two tickets purchased by same person"
when
$t1 : Ticket($o : owner)
$t2 : Ticket(owner == $o, this != $t1)
then
do something...
end
There are a multitude of ways to do this with non-drools constructs (a member flag the rule flips for example), but is there a way to do this type of check with a native drools construct (and keep the facts in the knowledge base), rather than use a java workaround
Thanks
The standard design pattern is to use a key attribute to force an order on the pair. Tickets might have a serial number:
$t1 : Ticket($o : owner, $sno: serialNumber )
$t2 : Ticket(owner == $o, serialNumber > $sno )
This eliminates the need for the constraint forcing different objects.
But three or more tickets would still create a similar problem. Therefore, you might also keep track of the tickets of an owner:
rule "insert Owner"
when
$t: Ticket( $o: owner )
not TicketSet( owner == $o )
then
insert( new TicketSet( $t ) );
end
rule "more tickets of one Owner"
when
$t: Ticket( $o: owner )
$s: TicketSet( owner == $o, set not contains $t )
then
modify( $s ){ add( $t ) }
// $o buys n-th ticket
end
Related
I am fairly new to Power BI and DAX and I am struggling with getting the below measure to work (I have provided to different version of what I have tried). I am trying to COUNTA the # of items that met certain criteria in two separate columns. Each column that the measure looks at has at least 3 filter criteria and in column two I need to use wildcards as the data there in has entries that share the first two values but the 3rd value could change over time. Any assistance would be amazing as I have tried dozens of different ways and I still cannot figure it out.
GA = CALCULATE(COUNTA(Table,[Item]),filter(Table,Table[Column 1]in{"GA","SP"}) , Filter(Table,Table[Column2]in{"MT*","GA*","SP*","OP*"}))
GA = CALCULATE(COUNTA(Table[Item]),Table[Column1]= "GA" || Table[Column1]= "SP" && Table[Column2]="GA*" || Table[Column2]= "OP*" || Table[Column2]]= "SP*" || Table[Column2]= "MT*")
Unfortunately I cannot provide an example of the data.
Thank you in advance
As #Alexis Olson mentions in his reply to this post, there does not appear to be a shorthand way to use the IN operator with wildcards.
Hence:
GA =
CALCULATE(
COUNTROWS( 'Table' ),
FILTER(
'Table',
'Table'[Column1]
IN { "GA", "SP" }
&& (
CONTAINSSTRING( 'Table'[Column2], "MT" )
|| CONTAINSSTRING( 'Table'[Column2], "GA" )
|| CONTAINSSTRING( 'Table'[Column2], "SP" )
|| CONTAINSSTRING( 'Table'[Column2], "OP" )
)
)
)
my case is similar to this case: Click here!
I have a gallery which displays items from a Collection. I already added a Textinput.Text to give customers the opportunity to search for items.
But, what I am struggling with is to implement a "full-text" search.
The solution #carlosfigueira offered in the above-mentioned question works perfectly to split the search text but I would like to have display items on the gallery only that includes all individual strings.
This is my code for items on the gallery
Filter(
CustomListIssues;
Sum(
ForAll(
Filter(
Split(
InpSearchString.Text;
" "
);
Len(Trim(Result)) > 0
);
If(
Result in 'Title EN';
1;
0
) && "Unresolved" = Status && If(
!IsEmpty(lbSearchDepartment.SelectedItems.Result);
lbSearchDepartment.Selected.Value = Departement;
"" in Departement
)
);
Value
) > 0
)
CustomListIssues: A collection where I store all list items
InpSearchString.Text: Search TextInput.Text
'Title EN': The column I would like to search in based on the given search string
Overview App:
Image below to give you an overview of how it looks/works at the moment
Given search string
Trim(InpSearchString.Text)
The gallery which displays items from a Collection
Expected result:
I would like to have display items on the gallery only that includes all individual strings
Thanks in advance
Sascha Dornig
If you want to have all strings instead of one of them, you can slightly change the logic of the expression. Before it would sum 1 if a word is in the title, and check that the result is more than 0 (so if any is present, then the item would be returned). In this modified expression below, we're adding 1 if each word is not in the title, and at the end we compare the sum with 0 - if it's not zero, then at least one word was not found, and we don't return the record.
Filter(
CustomListIssues;
Sum(
ForAll(
Filter(
Split(
InpSearchString.Text;
" "
);
Len(Trim(Result)) > 0
);
If(
Result in 'Title EN';
0;
1
) && "Unresolved" = Status && If(
!IsEmpty(lbSearchDepartment.SelectedItems.Result);
lbSearchDepartment.Selected.Value = Departement;
"" in Departement
)
);
Value
) = 0
)
I have a "movies" table and I need to add a constraint to the effect that "Steven Spielberg" movies must be before 1990 and "James Cameron" movies must be after 1990.
I am new to Oracle SQL. I tried some queries but they did not work. Something like
alter table movie_16bce1346 add constraint chk_spk
if director='Steven Spielberg' then check (year>1990);
What's the right way to write this constraint?
The constraint should be something like this:
( director not in ('Steven Spielberg', 'James Cameron') or
director is null /* if that is allowed */ or
director = 'Steven Spielberg' and movie_year < 1990 or
director = 'James Cameron' and movie_year > 1990 )
You could use parentheses around the AND-separated conditions in lines 3 and 4, if you don't trust your developers to be very familiar and comfortable with the precedence of AND and OR.
You can use a CASE statement within a CHECK constraint:
ALTER TABLE movie_16bce1346
ADD CONSTRAINT check_year CHECK
(CASE
WHEN director = 'Steven Spielberg' AND movie_year > 1990 THEN 1
WHEN director = 'James Cameron' AND movie_year < 1990 THEN 1
WHEN director NOT IN ('Steven Spielberg', 'James Cameron') THEN 1
ELSE 0 END = 1);
The CASE captures your conditions, which need to return a 1 or 0. The "END = 1" says that the result of the CASE needs to equal 1.
I am new to Prolog and wanted to access specific elements of the list.For eg-
L=[name,age,height,weight,gender]
How can I access age and height from this list as I want to compare them with some given values???
A list is not intended to be used as a record. Anyway, just use unification
L = [Name,Age,Height,Weight,Gender],
( Gender == male -> ... ; ... )
I'd like to select data property values using sparql with some restrictions on their languages:
I have an ordered set of preferred languages ("ru", "en", ... etc )
If an item have more than one language for value, I'd like to have only one value restricted by my set of languages (if ru is available - I want to see ru value, else if en available I want to see en else if ... etc if no lang available - no lang value).
Current query is:
select distinct ?dataProperty ?dpropertyValue where {
<http://dbpedia.org/resource/Blackmore's_Night> ?dataProperty ?dpropertyValue.
?dataProperty a owl:DatatypeProperty.
FILTER ( langmatches(lang(?dpropertyValue),"ru") || langmatches(lang(? dpropertyValue),"en") || lang(?dpropertyValue)="" )
}
The problem with it: results contain two rows for abstract (ru+en). I want only one row, which should contain ru. In case when ru is not available I'd like to get en etc.
How?
Suppose you have data like this:
#prefix : <http://stackoverflow.com/q/21531063/1281433/> .
:a a :resource;
:p "a in english"#en, "a in russian"#ru .
:b a :resource ;
:p "b in english"#en .
Then you're hoping to get results like this:
--------------------------------
| resource | label |
================================
| :b | "b in english"#en |
| :a | "a in russian"#ru |
--------------------------------
Here are two ways of doing this.
Associate language tags with ranks, find the rank of the best label, then find the label with that rank
This way uses SPARQL 1.1 subqueries, aggregates, and data provided with values. The idea is to use values to associate each language tag with a rank. Then you use a subquery to pull out the optimal rank over all the labels that the resource has). Then in the outer query, you have access to the optimal rank, and you just retrieve the label with the language corresponding to that rank.
prefix : <http://stackoverflow.com/q/21531063/1281433/>
select ?resource ?label where {
# for each resource, find the rank of the
# language of the most preferred label.
{
select ?resource (min(?rank) as ?langRank) where {
values (?lang ?rank) { ("ru" 1) ("en" 2) }
?resource :p ?label .
filter(langMatches(lang(?label),?lang))
}
group by ?resource
}
# ?langRank from the subquery is, for each
# resource, the best preference. With the
# values clause, we get just the language
# that we want.
values (?lang ?langRank) { ("ru" 1) ("en" 2) }
?resource a :resource ; :p ?label .
filter(langMatches(lang(?label),?lang))
}
Select the labels separately and coalesce in the order that you want
You can select an optional label for each of the languages you're considering, and then coalesce them into (so you get the first one that's bound) in the order of your preference. This is kind of verbose, but if you need to do anything else with the labels in various languages other than the most preferred, you'll have access to them.
prefix : <http://stackoverflow.com/q/21531063/1281433/>
select ?resource ?label where {
# find resources
?resource a :resource .
# grab a russian label, if available
optional {
?resource :p ?rulabel .
filter( langMatches(lang(?rulabel),"ru") )
}
# grab an english label, if available
optional {
?resource :p ?enlabel .
filter( langMatches(lang(?enlabel),"en") )
}
# take either as the label, but russian over english
bind( coalesce( ?rulabel, ?enlabel ) as ?label )
}