db4o的SODA查询貌似不支持正则匹配。API中关于Constraint接口的Method Summary如下
Method Summary Constraint |
and (Constraint with) links two Constraints for AND evaluation. |
Constraint |
byExample () set the evaluation mode to object comparison (query by example). |
Constraint |
contains () sets the evaluation mode to containment comparison. |
Constraint |
endsWith (boolean caseSensitive) sets the evaluation mode to string endsWith comparison. |
Constraint |
equal () Used in conjunction with smaller() or greater() to create constraints like "smaller or equal", "greater or equal". |
java.lang.Object |
getObject () returns the Object the query graph was constrained with to create this Constraint . |
Constraint |
greater () sets the evaluation mode to > . |
Constraint |
identity () sets the evaluation mode to identity comparison. |
Constraint |
like () sets the evaluation mode to "like" comparison. |
Constraint |
not () turns on not() comparison. |
Constraint |
or (Constraint with) links two Constraints for OR evaluation. |
Constraint |
smaller () sets the evaluation mode to < . |
Constraint |
startsWith (boolean caseSensitive) sets the evaluation mode to string startsWith comparison. |
endsWith跟
startsWith只提供了很弱的字符串匹配功能,不能实现正则表达式模式的匹配。
在db4o论坛找到这么一个帖子(http://developer.db4o.com/Forums/tabid/98/aft/10103/Default.aspx),有个叫gamlerhart的人的回复很有意思。
11 Aug 2010 10:51 AM | |
Just a note to the Regex-Evaluation. It's possible to make it more generic. Build an evaluator to run the regex against a string. Then descend to the string-field and use the evaluator on this. Like this.
And then you can use it on any string-field:
|
受gamlerhart的启发,对db4o源代码hack如下:
1. 在com.db4o.query加入新的类RegexConstraint
package com.db4o.query; import java.util.regex.Pattern; /** * Created by IntelliJ IDEA. * User: S.C. * Date: Dec 9, 2010 * Time: 11:31:07 AM * * RegexConstraint, a constraint or an evaluation? If it works, who the hell cares? */ public class RegexConstraint implements Evaluation { private final Pattern pattern; public RegexConstraint(Pattern pattern) { this.pattern = pattern; } public void evaluate(Candidate candidate) { String stringValue = (String) candidate.getObject(); candidate.include(pattern.matcher(stringValue).matches()); } }
2. 修改com.db4o.internal.query.processor.QQueryBase#constrain
public Constraint constrain(Object example) { // +by S.C. 09-Dec-2010 ==> if(example instanceof Pattern) { return constrain(new RegexConstraint((Pattern)example)); } // +by S.C. 09-Dec-2010 <== synchronized (streamLock()) { ReflectClass claxx = reflectClassForClass(example); if (claxx != null) { return addClassConstraint(claxx); } QConEvaluation eval = Platform4.evaluationCreate(_trans, example); if (eval != null) { return addEvaluationToAllConstraints(eval); } Collection4 constraints = new Collection4(); addConstraint(constraints, example); return toConstraint(constraints); } }
只有寥寥几行代码,但我们在用SODA查询的时候却有了强大的正则匹配支持:
println "All subjects:" Subject.findAll().each{println it.randomizationNo} println "Subjects with randomizationNo ending with a hyphen followed by 4 digits:" Subject.findAll(randomizationNo:~/.*\-\d{4}/).each{println it.randomizationNo}
输出结果如下
All subjects:
022-0104
01171
01049
01074
01169
01051
01001
01145
01025
01075
Subjects with randomizationNo ending with a hypen followed by 4 digits:
022-0104