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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值