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.
private static class RegexConstrain implements Evaluation { private final Pattern pattern; public RegexConstrain(String pattern) { this.pattern = Pattern.compile(pattern); } public void evaluate(Candidate candidate) { String stringValue = (String) candidate.getObject(); candidate.include(pattern.matcher(stringValue).matches()); } } And then you can use it on any string-field: Query query = container.query(); query.constrain(Pilot.class); query.descend("name").constrain(new RegexConstrain("J.*nn.*")); ObjectSet result = query.execute(); |
受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