1

我正在尝试使用 Lucene 查询具有以下结构的域

Student 1-------* Attendance *---------1 Course

域中的数据总结如下

Course.name   Attendance.mandatory   Student.name
-------------------------------------------------
cooking       N                      Bob
art           Y                      Bob

如果我执行查询"courseName:cooking AND mandatory:Y",它会返回 Bob,因为 Bob 正在参加烹饪课程,而 Bob 也在参加必修课程。但是,我真正想查询的是“参加强制性烹饪课程的学生”,在这种情况下不会返回任何人。

是否可以将其表述为 Lucene 查询?我实际上使用的是 Compass,而不是直接使用 Lucene,所以我可以使用CompassQueryBuilder或 Lucene 的查询语言。

为了完整起见,域类本身如下所示。这些类是 Grails 域类,但我使用的是标准 Compass 注释和 Lucene 查询语法。

@Searchable
class Student {

    @SearchableProperty(accessor = 'property')
    String name

    static hasMany = [attendances: Attendance]

    @SearchableId(accessor = 'property')
    Long id

    @SearchableComponent
    Set<Attendance> getAttendances() {
        return attendances
    }
}

@Searchable(root = false)
class Attendance {

    static belongsTo = [student: Student, course: Course]

    @SearchableProperty(accessor = 'property')
    String mandatory = "Y"

    @SearchableId(accessor = 'property')
    Long id

    @SearchableComponent
    Course getCourse() {
        return course
    }
}

@Searchable(root = false)
class Course {

    @SearchableProperty(accessor = 'property', name = "courseName")
    String name  

    @SearchableId(accessor = 'property')
    Long id
}
4

4 回答 4

4

您尝试执行的操作有时称为“范围搜索”或“xml 搜索”——基于一组相关子元素进行搜索的能力。Lucene 本身不支持此功能,但您可以采取一些技巧使其正常工作。

您可以将与学生关联的所有课程数据放在一个字段中。然后在每门课程的术语之间将术语位置提高一个固定的量(如 100)。然后,您可以使用短语查询或跨度查询进行邻近搜索,以强制匹配单个课程的属性。这就是 Solr 支持多值字段的方式。

于 2009-07-29T21:32:22.860 回答
2

另一种解决方法是添加假 getter 并将其编入索引

就像是:

@SearchableComponent
Course getCourseMandatory() {
    return course + mandatory;
}
于 2009-11-23T15:19:41.187 回答
-1

尝试

+courseName:cooking +mandatory:Y

我们使用非常相似的查询,这对我们有用:

+ProdLineNum:1920b +HouseBrand:1

这将选择产品线 1920b 中的所有产品,该产品线也是自有品牌(通用)。

于 2009-07-29T19:31:20.480 回答
-1

您可以将查询创建为文本字符串,然后对其进行解析以获取您的查询对象。假设您已经看过Apache Lucene - 查询解析器语法

于 2009-07-29T19:34:01.160 回答