java - 通过 JCR 实现基于标签的搜索系统的最佳方法,如 Modeshape

标签 java tags jcr modeshape

我需要一个像 Modeshape 这样的 JCR 基于标签的搜索系统。我想通过一些标签搜索节点。
问题是实现它的最佳方法是什么?

  • 为标签添加新的节点类型和混合
    所以如果这是真的,我在哪里可以定义用户可以查看的标签名称?
  • 实现标签层次结构并在我的节点中引用它们。
    所以如果这是真的,我该如何引用它们?
  • 任何其他方式。
  • 最佳答案

    有几种方法可以在 JCR 中实现标签。您选择哪个选项取决于您自己的应用程序的需要。以下是我所知道的四个选项。

    选项 1:使用 Mixins

    为每个标签定义一个混合节点类型定义,它是一个标记混合(它没有属性定义或子节点定义),使用 NodeTypeManager 动态注册它们。然后,当您想要“标记”一个节点时,只需向该节点添加代表标记的 mixin。任何节点都可以有多个标签,您可以查询具有特定标签的所有节点。

    (在此响应的其余部分,“acme”用作通用命名空间。您应该将其替换为适合您自己的应用程序和组织的命名空间。)

    例如,给定一个标签“acme:tag1”,你可以通过简单的查询找到所有具有这个标签的节点:

    SELECT * FROM [acme:tag1]
    

    这种方法的缺点是维护标签很麻烦。创建新标签需要注册新的节点类型。您不能轻松地重命名标签,而是必须为具有新名称的标签创建 mixin;找到所有包含表示旧标签的 mixin 的节点,删除旧的 mixin,并添加新的 mixin;最后删除旧标签的节点类型定义(在它不再在任何地方使用之后)。以类似的方式删除旧标签。另一个缺点是不容易将额外的元数据(例如,显示名称)与标签相关联,因为节点类型定义不允许额外的属性。

    这种方法应该表现得很好。

    选项 2:使用分类法和强引用

    在这种方法中,您将在存储库的一个区域中创建一个简单的节点结构,您可以在其中为每个标签(例如,分类法)创建一个节点。在此节点上,您可以设置描述标签的属性(例如,显示名称);这些属性可以随时更改(例如,重命名标签)。

    然后要将标签“应用”到节点,您只需创建与标签的某种关系。一种方法是定义包含类型为 REFERENCE 的“acme:tags”多值属性的 mixin 节点类型。当您想将一个或多个标签应用于节点时,只需将 mixin 添加到节点并将“acme:tags”属性设置为标签节点。

    要查找特定标签的所有节点,您可以在标签节点上调用“getReferences()”以查找包含对标签节点的引用的所有节点。

    这种方法的好处是必须在一个或多个分类法(可能包括特定于用户的分类法)内控制/管理所有标签。但是,也有一些缺点。首先,REFERENCE 属性的性能可能不是很好。一些 JCR 实现完全不鼓励使用 REFERENCES。 ModeShape 不会,但是当有很多节点包含对同一节点的引用(例如,很多节点具有单个标签)时,ModeShape 可能会开始降低 REFERENCE 性能。

    选项 3:使用分类法和弱引用

    此选项是类似于上述选项 2 的混合体,不同之处在于“acme:tags”属性将是 WEAKREFERENCE 而不是 REFERENCE。您仍将定义和管理一个或多个分类法。要查找具有特定标记的节点,您不能在标记节点上使用“getReferences()”方法(因为它们不适用于 WEAKREFERENCE 属性),但您可以通过查询轻松完成此操作:

    SELECT * FROM [acme:taggable] AS taggable 
    JOIN [acme:tag] AS tag ON taggable.[acme:tags] = tag.[jcr:uuid]
    AND LOCALNAME(tag) = 'tag1'
    

    这种方法确实强制使用一个或多个分类法,使控制标签更容易一些,因为它们必须存在于分类法中才能使用。重命名和删除也更容易。在性能方面,这比 REFERENCE 方法要好,因为 WEAKREFERENCE 属性在处理大量引用时性能更好,无论它们是否都指向一个节点或多个节点。

    缺点是即使标签仍在使用,您也可以将其删除,但包含对该已删除标签的 WEAKREFERENCE 的节点将不再有效。这可以通过应用程序中的一些约定来解决,或者简单地使用分类法上的元数据来说明特定标签已“弃用”并且不应使用。 (IMO,后者实际上是这种方法的一个好处。)

    此选项的性能和扩展性通常比选项 2 好得多。

    选项 4:使用字符串属性

    另一种方法是简单地使用 STRING 属性用要应用的标签的名称来标记每个节点。例如,您可以定义一个定义多值 STRING 属性的 mixin(例如,“acme:taggable”),并且当您想要标记一个节点时,只需添加 mixin(如果尚未存在)并添加名称标记为 "acme:tags"STRING 属性上的值(同样,如果它尚未作为值存在)。

    这种方法的主要优点是非常简单:您只需在要标记的节点上使用字符串值。要查找使用特定标签(例如,“tag1”)标记的所有节点,只需发出查询:

    SELECT * 
    FROM [acme:taggable] AS taggable 
    WHERE taggable.[acme:tags] = 'tag1'
    

    标签的管理很简单:无需管理。如果要重命名标记,则可以重命名标记值。如果要删除标签(并从用它标记的节点中删除),则可以通过从“acme:tags”属性中删除值来完成(可能在后台作业中)。

    请注意,这允许使用任何标签名称,因此最适合标签名称完全不受控制的情况。如果您想控制用作标签值的字符串列表,只需在存储库中创建一个分类法(如上面的选项 2 和 3 所述)并让您的应用程序将值限制为分类法中的值。您甚至可以有多个分类法,其中一些可能是特定于用户的。但是这种方法与选项 2 或 3 的控制方式不同。

    此选项的性能会比选项 3 好一点(因为查询更简单),但也可以扩展。

    关于java - 通过 JCR 实现基于标签的搜索系统的最佳方法,如 Modeshape,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14315031/

    相关文章:

    autocomplete - Sublime Text 3 "wrap selection with tag"和 HTML 自动完成无法正常工作

    ios - isKindOfClass 抓取标签

    java - 如何在 Modeshape 4 中为自己的节点类型注册命名空间

    java - 如何自定义 JComboBox 以便弹出窗口是 JTree(而不是列表)?

    java - Osmdroid:单击时显示和隐藏标记描述

    wordpress - 使用 if is_page() Wordpress 条件语句

    persistence - 什么时候应该使用 JCR,什么时候应该使用 JPA/RDBMS?

    java - 获取节点属性时出现问题

    java - android/rails 分段上传问题

    java - JEST 批量请求问题