如何在 Play Morphia 中动态组合 OR 查询中的多个条件

Posted

技术标签:

【中文标题】如何在 Play Morphia 中动态组合 OR 查询中的多个条件【英文标题】:How to combine multiple criteria in OR query dynamically in Play Morphia 【发布时间】:2012-10-01 10:04:38 【问题描述】:

我正在尝试使用一种构建器模式来构建 OR 查询,根据场景使用多个条件。一个例子是

    public class Stylist extends Model 

      public String firstName;

      public String lastName;

      public String status;

      ...

      

如果名字或姓氏与给定字符串匹配并且状态与另一个字符串匹配,我想搜索 Stylist 集合。我正在编写如下查询:

      MorphiaQuery query = Stylist.q();
      if (some condition) 
      query.or(query.criteria("status").equal("PendingApproval"), query.criteria("status").equal(EntityStatus.ACTIVE));    
      

      if (some other condition as well) 
      query.or(query.criteria("firstName").containsIgnoreCase(name), query.criteria("lastName").containsIgnoreCase(name));
      

当两个条件都满足时,我看到查询仅包含与 firstName 和 lastName 相关的条件,即不添加/附加不同的 OR 条件而是覆盖。它与附加所有不同过滤条件的过滤条件完全不同,您可以轻松构建包含多个 AND 条件的查询。

我可以通过以不同的方式设置条件并以不同的方式构建查询来解决问题,但这似乎不是一种优雅的方式。我是不是做错了什么?

我正在使用 Play!框架 1.2.4 和 Play Morphia 模块版本 1.2.5a

更新

为了更清楚地说,我想 AND 多个 OR 查询。具体来说,在上述场景中,我想

我想在哪里搜索造型师:

firstName or lastName contains supplied name AND

status equals ACTIVE or PENDING_APPROVAL.

我已经能够通过以下方式直接在 Mongo shell 上构建查询:

db.stylists.find($and: [$or : [status: "PENDING_APPROVAL", status : "ACTIVE"],$or : [firstName : "$regex" : "test" , "$options" : "i", lastName : "$regex" : "test" , "$options" : "i"]] ).pretty();

但无法通过 Query API 方法实现相同的目的。这是我的尝试:

    Query<Stylist> query = MorphiaPlugin.ds().find(Stylist.class);

    CriteriaContainer or3 = query.or(query.criteria("firstName").containsIgnoreCase(name), query.criteria("lastName").containsIgnoreCase(name));

    CriteriaContainer or4 = query.or(query.criteria("status").equal("PENDING_APPROVAL"), query.criteria("status").equal("ACTIVE"));

    query.and(or3, or4);

query.toString() 产生以下输出: "$or" : [ "status" : "PENDING_APPROVAL" , "status" : "ACTIVE"]

不确定,我错过了什么?

【问题讨论】:

【参考方案1】:

我想可能有两种方法可以处理您的案件:

首先,使用List&lt;Criteria&gt;

MorphiaQuery query = Stylist.q();
List<Criteria> l = new ArrayList<Criteria>()

if (some condition) 
  l.add(query.criteria("status").equals("PendingApproval");
  l.add(query.criteria("status").equal(EntityStatus.ACTIVE));


if (some other conditional as well) 
  l.add(query.criteria("firstName").containsIgnoreCase(name));
  l.add(query.criteria("lastName").containsIgnoreCase(name));


query.or(l.toArray());

其次,使用CritieriaContainer

MorphiaQuery query = Stylist.q();
CriteriaContainer cc = null;

if (some condition) 
  cc = query.or(query.criteria("status").equal("PendingApproval"), query.criteria("status").equal(EntityStatus.ACTIVE));


if (some other condition) 
  if (null != cc) query.or(cc, query.criteria("firstName").containsIgnoreCase(name), query.criteria("lastName").containsIgnoreCase(name));
  else query.or(query.criteria("firstName").containsIgnoreCase(name), query.criteria("lastName").containsIgnoreCase(name));

【讨论】:

感谢@green,它解决了问题。我的问题应该改写为:如何使用 Morphia 进行多个 OR 查询?虽然这种方法解决了问题,但它涉及跨多个方法传递 CriteriaContainer 对象。我可以从查询对象中获取 CriteriaContainer 对象吗? 对不起@green,误报。您建议的两个选项都没有按预期工作。它似乎仍然忽略了早期的标准(与状态相关),只考虑了与 firstName / lastName 相关的标准。 顺便说一句,link 上有一个线程似乎表明仍然不支持直接对多个 OR 查询进行 ANDing。

以上是关于如何在 Play Morphia 中动态组合 OR 查询中的多个条件的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别