【问题标题】:What is the most effective way to create a search filter for both single and compound terms?为单个和复合词创建搜索过滤器的最有效方法是什么?
【发布时间】:2019-05-16 13:33:43
【问题描述】:

我们有一种情况,我们正在进行搜索,用户可以提供一个项目列表作为搜索的过滤器。

例如,假设我们正在搜索包含特定食物的食谱。我们可能有一份可能的食物清单,例如:

  • 牛肉
  • 胡萝卜
  • 豌豆
  • 洋葱
  • 大米
  • 豆子

但我们也希望用户能够搜索“任何肉类”或“任何蔬菜”,并让它返回与所有肉类可能性或所有蔬菜可能性相匹配的任何内容。

我们可以让客户端进行解析,当用户选择“肉类”时,发送所有肉类选择。但是当用户选择这样的更高类别时,我们还需要执行其他逻辑。例如,如果他们选择“任何肉类”,我们可以搜索一个额外的数据库,其中包含标记为“肉类”的食谱,而不是单个肉类。

(我正在根据我们实际的业务需求来编造这个例子,这些需求要枯燥得多,但本质上是这个想法。)

我能想到几个可能的解决方案,它们是同一件事的阴影:

  • 在搜索条件中有两个不同的列表,一个用于枚举 单个项目和一个用于一组枚举,然后将两者结合起来 过滤搜索时。
  • 在搜索条件中有一个列表,其中包含一个枚举 单个项目和组项目。

但我觉得我缺少一个在代表群体/个人关系方面可能更优雅的解决方案。有解决这种情况的模式吗?

(PS:这是在Java中,但我认为这并不重要。)

【问题讨论】:

  • Map<Type, Set<Dish>> 怎么样,其中TypemeatSet<Dish>fish, carrots...,得到TypeO(1)Set::contains 又是@98765432

标签: java search design-patterns enums


【解决方案1】:

为了获得最大的灵活性,您可以申请Composite design pattern。它允许您像处理任何其他查询一样处理复合查询(例如,“任何肉类”)。在您的情况下,对叶子使用枚举是有意义的。

首先你需要一个父接口类型。在这种情况下,我们可以包含一个返回查询中所有单个术语的方法。

public interface Query {    
    EnumSet<Term> getTerms();
}

然后对于单个术语,使用将自身返回为术语“列表”的枚举:

public enum Term implements Query {
    BEEF, CHICKEN, FISH, CARROTS, PEAS, ONIONS, RICE, BEANS;

    @Override
    public EnumSet<Term> getTerms() {
        return EnumSet.of(this);
    }
}

对于您使用复合类的术语组:

public class CompositeQuery implements Query {

    private final List<Query> queries;

    public CompositeQuery( Query... queries ) {
        this.queries = Arrays.asList(queries);
    }

    @Override
    public EnumSet<Term> getTerms() {
        Set<Term> result = new HashSet<>();
        for( Query query : queries ) {
            result.addAll(query.getTerms());
        }
        return EnumSet.copyOf(result);
    }
}

对于默认组,您可以定义常量(我会在Query 接口中声明这些):

Query MEAT = new CompositeQuery(Term.BEEF, Term.CHICKEN);
Query VEGETABLES = new CompositeQuery(Term.CARROTS, Term.ONIONS, Term.PEAS);

Composite 甚至允许您拥有多个组:

Query MEAT_VEGETABLES = new CompositeQuery( MEAT, VEGETABLES );

【讨论】:

  • 这是有道理的。我什至可以使复合查询成为枚举的成员或以某种方式关联它们,以便 JAXB 可以解组叶子和复合。谢谢!
【解决方案2】:

在搜索任何内容时,Apache SOLR 和 Elastic Search 是最好的。您可以在上述框架中进行所有类型分组、分类和其他类型搜索。我会建议利用 Apache Solr 或 Elastic 搜索,而不是从头开始编写代码。

【讨论】:

  • 我在非常具体的领域搜索现有的遗留数据库。我没有能力导入和索引数据库中的所有内容(现有的或新添加的)。加上我的代码已经写好了,除了这个新功能。我将查看文档以了解这些工具如何允许我正在寻找的标准措辞。谢谢。
  • @Risser,不需要索引数据库中的所有内容,使用 Apache Solr。 Solr 中有一个工具可以从数据库表中导入,它可以做索引。之后你可以搜索任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多