db4o SODA query hacking之正则匹配支持

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的人的回复很有意思。

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

你可能感兴趣的:(C++,c,正则表达式,C#,idea)