Java Lucene:按字段搜索/筛选';s值长度

Java Lucene:按字段搜索/筛选';s值长度,java,search,lucene,Java,Search,Lucene,我需要一些人帮我搜索。 假设我有一个非常简单的文档结构,只有一个字段,标记为name。 我需要检索长度大于或小于指定值的所有名称。我所说的长度是指String.length()。 范围过滤器在概念上似乎很接近,但我找不到一个好的例子来写我的具体案例。 感谢您的帮助。这是一个典型的多术语查询示例。它不在盒子里,但很容易实现。看看扩展了多项查询的通配符查询。这是非常相似的。只需使用另一个FilterredTerminum,如此,它使用term.text的长度来过滤术语(而不是术语文本本身) 神奇发生

我需要一些人帮我搜索。 假设我有一个非常简单的文档结构,只有一个字段,标记为name。 我需要检索长度大于或小于指定值的所有名称。我所说的长度是指String.length()。 范围过滤器在概念上似乎很接近,但我找不到一个好的例子来写我的具体案例。
感谢您的帮助。

这是一个典型的多术语查询示例。它不在盒子里,但很容易实现。看看扩展了
多项查询的
通配符查询
。这是非常相似的。只需使用另一个FilterredTerminum,如此,它使用term.text的长度来过滤术语(而不是术语文本本身)

神奇发生在这里(这段代码在我文章底部的自定义术语枚举器中):

上面的代码检查了字段的所有术语,并根据在构造函数中传递的术语的长度检查它们的长度。对于任何至少那么长的字段,它都是正确的

public class MinLengthQuery : MultiTermQuery
{
  public MinLengthQuery(Term term) : base(term)
  {
  }

  protected internal override FilteredTermEnum GetEnum(IndexReader reader)
  {
    return new MinLengthTermEnum(reader, GetTerm());
  }
}
本课程完成所有工作:

public class MinLengthTermEnum : FilteredTermEnum
{
internal Term searchTerm;
internal System.String field = "";
internal System.String text = "";
internal System.String pre = "";
internal int preLen = 0;
internal bool endEnum = false;

public MinLengthTermEnum(IndexReader reader, Term term):base()
{
  searchTerm = term;
  field = searchTerm.Field();
  text = searchTerm.Text();
  SetEnum(reader.Terms(new Term(searchTerm.Field(), "")));
}

protected internal override bool TermCompare(Term term)
{
  if (field == term.Field())
  {
    System.String searchText = term.Text();
    if (searchText.Length >= text.Length())
    {
      return true;
    }
  }
  endEnum = true;
  return false;
}

public override float Difference()
{
  return 1.0f;
}

public override bool EndEnum()
{
  return endEnum;
}
public override void  Close()
{
  base.Close();
  searchTerm = null;
  field = null;
  text = null;
}
}

(我是一个lucene.net的家伙,但是翻译应该很简单……从您的lucene版本的WildCardQuery和TermEnum源代码开始并从中开始工作可能会更容易)。

使用长度添加一个数字字段,然后使用RangeQuery。有关示例,请参见NumericField javadoc。

最简单的解决方案似乎是创建第二个包含长度的字段。我不确定如何使用
name
字段的索引来有效地按其长度进行查询。我想我可以创建该字段,按其索引,然后执行范围筛选/查询。在我看来,应该有一个更直接的解决方案,但这是一个很好的建议。可能有一个更直接的解决方案,我只是Lucene的新手(这就是为什么我写我的建议作为评论而不是答案),但这肯定是我会做的。我从Lucene用户列表中得到了相同的答案。我要再等一会儿,然后走那条路。如果您关心分数,可以将其添加为答案,我会将其标记为已解决。使用长度创建数字字段是一个合理的建议,然后您可以使用RangeQuery提取结果非常感谢您的详细答案!将其转换为java确实很容易。然而,我认为存在一个问题:这假设术语是按枚举标准排序的,我认为情况并非如此。如果索引包含以下内容:aaaa aabbbbbbbbbb…并且查询要求长度小于5,则似乎这将停止在第2个元素处枚举,并错过第3个元素。我调整了endEnum()方法以使用return actualnum.term()==null;这是可行的,但是这似乎将索引搜索转化为该术语的线性搜索。我用一个简单的查询和一个小数据库(~17k个文档)对其进行了测试,添加这个标准改变了查询时间,看起来我不像我想的那样理解这些东西。我是从臀部开始拍摄的,但它不应该确保它在正确的场地上拍摄。。。否则,它不会继续到下一个字段吗?(
actualnum.term().field()==expectedField | actualnum.term()==null
)。我认为TermEnumerator将从一个字段开始,遍历该字段的所有术语,然后前进到下一个字段。。。直到它到达最后一个字段的最后一个术语。我现在意识到我指的是文档,枚举器是关于术语的。这对我来说太费时了。我将尝试第一个建议,如果不起作用,我会回去尝试这个。还是非常感谢你的帮助!
public class MinLengthTermEnum : FilteredTermEnum
{
internal Term searchTerm;
internal System.String field = "";
internal System.String text = "";
internal System.String pre = "";
internal int preLen = 0;
internal bool endEnum = false;

public MinLengthTermEnum(IndexReader reader, Term term):base()
{
  searchTerm = term;
  field = searchTerm.Field();
  text = searchTerm.Text();
  SetEnum(reader.Terms(new Term(searchTerm.Field(), "")));
}

protected internal override bool TermCompare(Term term)
{
  if (field == term.Field())
  {
    System.String searchText = term.Text();
    if (searchText.Length >= text.Length())
    {
      return true;
    }
  }
  endEnum = true;
  return false;
}

public override float Difference()
{
  return 1.0f;
}

public override bool EndEnum()
{
  return endEnum;
}
public override void  Close()
{
  base.Close();
  searchTerm = null;
  field = null;
  text = null;
}
}