AEM Tagging Framework

要标记内容并利用AEM Tagging基础结构:

  • 标记必须作为分类根节点 [cq:Tag](#tags-cq-tag-node-type)类型的节点存在

  • 标记内容节点的NodeType必须包含 cq:Taggable mixin

  • TagID添加到内容节点的 cq:tags属性,并解析到类型为 [cq:Tag](#tags-cq-tag-node-type)的节点

标记:cq:标记节点类型

标记的声明捕获在cq:Tag.类型节点的存储库中

标签可以是简单的词(例如,sky)或表示分级分类(例如,水果/苹果,即通用水果和更具体的苹果)。

标记由唯一的TagID标识。

标记具有可选的元信息,如标题、本地化标题和描述。 标题应当显示在用户界面中,而不是TagID(如果存在)。

标记框架还允许限制作者和站点访客仅使用特定的预定义标记。

标记特征

  • 节点类型为cq:Tag

  • 节点名称是 [TagID](#tagid)的组件

  • [TagID](#tagid)始终包含命名空间

  • 可选jcr:title属性(要在UI中显示的标题)

  • 可选jcr:description属性

  • 包含子节点时,称为容器标签

  • 存储在名为分类根节点的基本路径下的存储库中

标记 ID

TagID标识解析到存储库中的标记节点的路径。

通常,TagID是从命名空间开始的短TagID,也可以是从分类根节点开始的绝对TagID。

标记内容时,如果内容尚不存在,则 [cq:tags](#tagged-content-cq-tags-property)属性将添加到内容节点,而TagID将添加到属性的String数组值。

TagID由命名空间和本地TagID组成。 容器 标签子标签,表示分类中的分层顺序。子标签可用于引用与任何本地TagID相同的标签。 例如,允许用“水果”标记内容,即使它是带有子标签的容器标签,如“水果/苹果”和“水果/香蕉”。

分类根节点

分类根节点是存储库中所有标记的基本路径。 分类根节点必须​​为 cq :Tag类型的节点。

在AEM中,基路径为/content/ cq :tags,根节点的类型为 cq :Folder

标记命名空间

命名空间允许对内容进行分组。 最典型的用例是每个(网站)(例如公共、内部和门户)或每个较大的应用程序(例如WCM、资产、社区)具有命名空间,但命名空间可用于各种其他需求。 命名空间在用户界面中用于仅显示适用于当前内容的标签子集(即特定命名空间的标签)。

标记的命名空间是分类子树中的第一级,该子树是紧挨分类根节点的节点。 命名空间是cq:Tag类型的节点,其父节点不是cq:Tag节点类型。

所有标记都具有命名空间。 如果未指定命名空间,则将标记分配给默认命名空间,即TagID default(标题为Standard Tags),,即/content/cq:tags/default.

容器标签

容器标记是cq:Tag类型的节点,包含任意数量和类型的子节点,这使得可以使用自定义元数据增强标记模型。

此外,分类中的容器标签(或超标签)用作所有子标签的子总和:例如,用水果/苹果标记的内容也被视为用水果标记,即搜索仅用水果标记的内容也会找到用水果/苹果标记的内容。

解析TagID

如果标记ID包含冒号“:”,则冒号将命名空间与标记或子分类分开,然后用正斜杠“/”分开。 如果标记ID没有冒号,则默示默认命名空间。

标记的标准和唯一位置位于/content/cq:tags下。

引用不指向cq:Tag节点的非现有路径或路径的标记被视为无效并被忽略。

下表显示了一些TagID示例、其元素,以及TagID如何解析为存储库中的绝对路径:

下表显示了一些TagID示例、其元素,以及TagID如何解析为存储库中的绝对路径:
下表显示了一些TagID示例、其元素,以及TagID如何解析为存储库中的绝对路径:

标记 ID
命名空间 本地ID 容器标签 Leaf标签 存储库
绝对标记路径
dam:fruit/apple/braeburn 水果/苹果/布雷本 水果,苹果 布雷本 /content/cq:tags/dam/fruit/apple/braeburn
color/red 默认 color/red 颜色 /content/cq:tags/default/color/red
天空 默认 天空 (无) 天空 /content/cq:tags/default/sky
dam: (无) (无) (无,命名空间) /content/cq:tags/dam
/content/cq:tags/类别/car 类别 汽车 汽车 汽车 /content/cq:tags/类别/car

本地化标记标题

当标记包含可选的标题字符串(jcr:title)时,可以通过添加属性jcr:title.<locale>来本地化显示的标题。

有关详细信息,请参阅

访问控制

标记作为节点存在于分类根节点下的存储库中。 允许或拒绝作者和站点访客在给定命名空间中创建标记,可以通过在存储库中设置适当的ACL。

此外,拒绝某些标签或命名空间的读取权限将控制将标签应用于特定内容的能力。

典型的做法包括:

  • 允许tag-administrators组/角色写入访问所有命名空间(在/content/cq:tags下添加/修改)。 此组随附AEM开箱即用。

  • 允许用户/作者读取应可读取的所有命名空间(大部分)。

  • 允许用户/作者对用户/作者可自由定义标签的命名空间(/content/cq:tags/some_namespace下的add_node)进行写入访问

可标记内容:cq:Taggable Mixin

为了使应用程序开发者能够将标记附加到内容类型,节点的注册(CND)必须包括cq:Taggable混音或cq:OwnerTaggable混音。

继承自cq:Taggablecq:OwnerTaggable混音旨在指示内容可由所有者/作者分类。 在AEM中,它只是cq:PageContent节点的属性。 标记框架不需要cq:OwnerTaggable混音。

注意

建议仅在聚合内容项的顶级节点(或其jcr:content节点)上启用标记。 示例包括:

  • 页面(cq:Page),其中jcr:content节点的类型为cq:PageContent,其中包含cq:Taggable mixin。

  • 资产(cq:Asset),其中jcr:content/metadata节点始终具有cq:Taggable mixin。

节点类型表示法(CND)

存储库中存在节点类型定义(CND文件)。 CND记号定义为JCR文档此处的一部分。

AEM中包含的节点类型的基本定义如下:

[cq:Tag] > mix:title, nt:base
    orderable
    - * (undefined) multiple
    - * (undefined)
    + * (nt:base) = cq:Tag version

[cq:Taggable]
    mixin
    - cq:tags (string) multiple

[cq:OwnerTaggable] > cq:Taggable
    mixin

标记内容:cq:tags属性

cq:tags属性是一个String数组,当作者或站点访客将一个或多个TagID应用于内容时,它们用于存储这些TagID。 仅当将该属性添加到用[cq:Taggable](#taggable-content-cq-taggable-mixin) mixin定义的节点时,该属性才有意义。

注意

要利用AEM标记功能,自定义开发的应用程序不应定义cq:tags以外的标记属性。

移动和合并标记

以下是使用标记控制台移动或合并标记时存储库中效果的说明:

  • 当标记A被移动或合并到/content/cq:tags下的标记B时:

    • 未删除标记A并获取cq:movedTo属性。
    • 将创建标记B(在移动时)并获取cq:backlinks属性。
  • cq:movedTo 指向标记B。此属性表示标记A已移动或合并到标记B中。移动标记B将相应地更新此属性。因此,标记A是隐藏的,仅保存在存储库中以解析指向标记A的内容节点中的标记ID。标记垃圾收集器会删除标记A等标记,而不再有指向它们的内容节点。
    cq:movedTo属性的特殊值为nirvana:在删除标记但无法从存储库中删除该标记时应用,因为必须保留具有cq:movedTo的子标记。

    注意

    cq:movedTo属性仅在满足以下任一条件时添加到移动或合并的标记:

    1. 标记用于内容(即它有引用)或
    2. 标记包含已移动的子项。
  • cq:backlinks 使引用保持在另一个方向,即保留已移动到标记B或与标记B合并的所有标记的列表。这主要是为了使属性在移动/合并/删除标记B以及激活标记B时保持最新,在这种情况下,必须同时激活其所有后台标记。 cq:movedTo

    注意

    cq:backlinks属性仅在满足以下任一条件时添加到移动或合并的标记:

    1. 标记用于内容(即它有引用)或 >
    2. 标记包含已移动的子项。
  • 读取内容节点的cq:tags属性涉及以下解决方法:

    1. 如果/content/cq:tags下没有匹配项,则不返回标记。

    2. 如果标记设置了cq:movedTo属性,则引用的标记ID将跟随。
      只要后面的标签具有cq:movedTo属性,就重复此步骤。

    3. 如果后面的标记没有cq:movedTo属性,则读取该标记。

  • 要在标记被移动或合并时发布更改,必须复制cq:Tag节点及其所有反向链接:在标记管理控制台中激活标记时,会自动执行此操作。

  • 稍后对页面的cq:tags属性的更新会自动清理“旧”引用。 触发这是因为通过API解析移动的标记会返回目标标记,从而提供目标标记ID。

注意

标记的移动不同于标记的迁移。

标记迁移

从Experience Manager 6.4开始的标签存储在/content/cq:tags下,而之前的标签存储在/etc/tags下。 但是,在已从先前版本升级Adobe Experience Manager的情况下,旧位置/etc/tags下仍存在标记。 在升级的系统中,需要在/content/cq:tags下迁移标记。

注意

在标记页面的“页面属性”中,建议使用标记ID(geometrixx-outdoors:activity/biking),而不是硬编码标记基本路径(例如,/etc/tags/geometrixx-outdoors/activity/biking)。

要列表标签,可使用com.day.cq.tagging.servlets.TagListServlet

注意

建议使用标签管理器API作为资源。

如果升级的AEM实例支持TagManager API

  1. 在组件开始,TagManager API会检测它是否是升级的AEM实例。 在升级的系统中,标记存储在/etc/tags下。

  2. 然后,TagManager API以向后兼容模式运行,这意味着API使用/etc/tags作为基本路径。 否则,将使用新位置/content/cq:tags

  3. 更新标记位置。

  4. 将标记迁移到新位置后,运行以下脚本:

import org.apache.sling.api.resource.*
import javax.jcr.*

ResourceResolverFactory resourceResolverFactory = osgi.getService(ResourceResolverFactory.class);
ResourceResolver resolver = resourceResolverFactory.getAdministrativeResourceResolver(null);
Session session = resolver.adaptTo(Session.class);

def queryManager = session.workspace.queryManager;
def statement = "/jcr:root/content/cq:tags//element(*, cq:Tag)[jcr:contains(@cq:movedTo,\'/etc/tags\') or jcr:contains(@cq:backlinks,\'/etc/tags\')]";
def query = queryManager.createQuery(statement, "xpath");

println "query = ${query.statement}\n";

def tags = query.execute().getNodes();


tags.each { node ->
  def tagPath = node.path;
  println "tag = ${tagPath}";

  if(node.hasProperty("cq:movedTo") && node.getProperty("cq:movedTo").getValue().toString().startsWith("/etc/tags"))
    {
     def movedTo = node.getProperty("cq:movedTo").getValue().toString();

     println "cq:movedTo = ${movedTo} \n";

     movedTo = movedTo.replace("/etc/tags","/content/cq:tags");
     node.setProperty("cq:movedTo",movedTo);
     } else if(node.hasProperty("cq:backlinks")){

     String[] backLinks = node.getProperty("cq:backlinks").getValues();
     int count = 0;

     backLinks.each { value ->
             if(value.startsWith("/etc/tags")){
                     println "cq:backlinks = ${value}\n";
                     backLinks[count] = value.replace("/etc/tags","/content/cq:tags");
    }
             count++;
     }

    node.setProperty("cq:backlinks",backLinks);
  }
}
session.save();

println "---------------------------------Success-------------------------------------"

脚本将获取cq:movedTo/cq:backLinks属性值中具有/etc/tags的所有标记。 然后,它迭代读取的结果集并将cq:movedTocq:backlinks属性值解析为/content/cq:tags路径(在该值中检测到/etc/tags的情况下)。

如果升级的AEM实例在经典UI上运行

注意

经典UI不符合零停机时间要求,也不支持新的标签基础路径。 如果要使用经典UI,则需要先创建/etc/tags,然后再重新启动cq-tagging组件。

如果AEM实例升级后由TagManager API支持并在经典UI中运行:

  1. 使用tagId或新标签位置/content/cq:tags替换对旧标签基路径/etc/tags的引用后,您可以将标签迁移到CRX中的新位置/content/cq:tags,然后重新启动组件。

  2. 将标记迁移到新位置后,运行上述脚本。

在此页面上

Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now