我知道如何通过JCR SQL2 查询在JCR中搜索某些内容。
但是,我想在某些情况下使用 Java,使用JCR API :javax.jcr.Node
等javax.jcr.NodeIterator
。
恐怕我会简单地通过自己编写代码来重新发明轮子。
是否有任何可用的东西(Gist
或Github
)else
?
您可以使用ItemVisitor递归遍历存储库,沿途收集与您的条件匹配的所有项目。
例如打印出 type 的所有属性Long
:
Node root = session.getRootNode();
root.accept(new ItemVisitor() {
@Override
public void visit(Property property) throws RepositoryException {
if (!property.isMultiple() && property.getType() == PropertyType.LONG) {
System.out.println(property.getName() + " = " + property.getLong());
}
}
@Override
public void visit(Node node1) throws RepositoryException {
NodeIterator children = node1.getNodes();
while (children.hasNext()) {
visit(children.nextNode());
}
}
});
您可以使用该SlingQuery。它受到 jQuery 的启发并遵循它的语法。您应该只使用它来搜索少量节点(最好在 100 以下),因为遍历查询很慢。
编辑
您的示例可能会转换为以下 SlingQueries(未测试):
SlingQuery.$(startResource).find("[name=teasers][title=awesome-teaser]")
SlingQuery.$(startResource).find("[name][controlName]")
SlingQuery 是Apache Sling的一部分,这就是为什么 github 存储库似乎被放弃了。
注意:您可以静态导入美元符号并在您的语法中删除对 SlingQuery 的静态访问,例如 $(resource).find("...");
我最终编写了自己的实现。
随意改进或添加评论以进行潜在的改进。
Java 可能不是通过 JCR 搜索的最有效方式,因此请注意性能损失(与 using 相比JCR SQL2
)。
但是,在某些情况下使用 JCR SQL2 会很烦人。例如:JCR SQL2 - JCR 浏览器中的结果查询顺序
我建议在树中尽可能低地启动您的搜索。
阅读每种方法上方的评论以找到我们的更多信息。
package com.nameoforganization.jcr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JcrSearchUtils {
private static final Logger log = LoggerFactory.getLogger(JcrUtil.class);
/*
* Recursive search in JCR tree: properties matching values
* Parameters:
* - node: node to start the search from
* - propertyValueConditions: properties searched along with the value expected for it
* - searchResults: set this to null when launching the search
*/
public static ArrayList<Node> searchRecursivelyPropMatchVal(Node node, HashMap<String, String> propertyValueConditions, ArrayList<Node> searchResults) {
if(searchResults == null){
searchResults = new ArrayList<Node>();
}
try{
NodeIterator list = node.getNodes();
while(list.hasNext()) {
Node currentSubNode = list.nextNode();
Boolean hasAllRequiredPropsAndVals = true;
for (Map.Entry<String, String> entry : propertyValueConditions.entrySet()) {
String propertyName = entry.getKey();
Object searchedValue = entry.getValue();
if ( !currentSubNode.hasProperty(propertyName) || !currentSubNode.getProperty(propertyName).getString().equals(searchedValue) ){
hasAllRequiredPropsAndVals = false;
}
}
if ( hasAllRequiredPropsAndVals ){
searchResults.add(currentSubNode);
}
searchRecursivelyPropMatchVal(currentSubNode, propertyValueConditions, searchResults);
}
return searchResults;
} catch (RepositoryException rpe){
log.info("Recursive search in JCR tree (properties matching values) via JCR API failed");
}
return null;
}
/*
* Recursive search in JCR tree: required properties present
* Parameters:
* - node: node to start the search from
* - propertyValueConditions: properties searched along with the value expected for it
* - searchResults: set this to null when launching the search
*/
public static ArrayList<Node> searchRecursivelyPropPres(Node node, ArrayList<String> propertyPresConditions, ArrayList<Node> searchResults) {
if(searchResults == null){
searchResults = new ArrayList<Node>();
}
try{
NodeIterator list = node.getNodes();
while(list.hasNext()) {
Node currentSubNode = list.nextNode();
Boolean hasAllRequiredProperties = true;
for (String propertyName : propertyPresConditions) {
if ( !currentSubNode.hasProperty(propertyName) ){
hasAllRequiredProperties = false;
}
}
if( hasAllRequiredProperties ){
searchResults.add(currentSubNode);
}
searchRecursivelyPropPres(currentSubNode, propertyPresConditions, searchResults);
}
return searchResults;
} catch (RepositoryException rpe){
log.info("Recursive search in JCR tree (required properties present) via JCR API failed");
}
return null;
}
}
/*
* Search nodes with properties:
* "name" having value "teasers"
* "title" having value "awesome-teaser"
*/
// Node startingNode = set this yourself :)
HashMap<String, String> propertyValueConditions = new HashMap<String, String>();
propertyValueConditions.put("name", "teasers");
propertyValueConditions.put("title", "awesome-teaser");
ArrayList<Node> nodesFound = JcrUtil.searchRecursivelyPropMatchVal(startingNode, propertyValueConditions, null);
/*
* Search nodes having properties "name" and "controlName"
*/
// Node startingNode = set this yourself :)
ArrayList<String> propertyPresConditions = new ArrayList<String>();
propertyPresConditions.add("name");
propertyPresConditions.add("controlName");
ArrayList<Node> nodesFound = JcrUtil.searchRecursivelyPropPres(startingNode, propertyPresConditions, null);