Retrieve a parent node using AEM query builder - aem

I need to retrieve a parent node using AEM Query builder.
For instance, this is my query:
path:/content/test/us/bar
1_property:product
1_property.operation:exists
2_property:product
2_property.value:8003170008212
This query allow me to retrieve the following elements:
1) /content/test/us/bar/table/jcr:content/releated/product/2
2) /content/test/us/bar/chair/jcr:content/releated/product/1
Using this query, one can retrieve all elements placed under /content/test/us/bar which contain 8003170008212 as value of product property.
Starting from the previous bullet points I need to return just the parent, so for example:
1) /content/test/us/bar/table
2) /content/test/us/bar/chair
I can achieve my target programmatically, iterating the results and using 3 times the getParent() method.
I'am wondering: is there a way to get it with query builder?

If the property that you are searching for is always present at a known path, the query can be rewritten as
path=/content/test/us/bar
1_property=jcr:content/related/product
1_property.operation=exists
2_property=jcr:content/related/product
2_property.value=8003170008212
This would then result in
/content/test/us/bar/table
/content/test/us/bar/chair
which avoids looping through the result and finding the parent nodes.
For e.g., the following query in my local environment
path=/content/we-retail/language-masters/en
1_property=displayMode
1_property.operation=exists
2_property=displayMode
2_property.value=singleText
results in
/content/we-retail/language-masters/en/experience/wester-australia-by-camper-van/jcr:content/root/responsivegrid/contentfragment
/content/we-retail/language-masters/en/experience/arctic-surfing-in-lofoten/jcr:content/root/responsivegrid/contentfragment
/content/we-retail/language-masters/en/experience/steelhead-and-spines-in-alaska/jcr:content/root/responsivegrid/contentfragment
/content/we-retail/language-masters/en/experience/hours-of-wilderness/jcr:content/root/responsivegrid/contentfragment
/content/we-retail/language-masters/en/experience/skitouring/jcr:content/root/responsivegrid/contentfragment
/content/we-retail/language-masters/en/experience/fly-fishing-the-amazon/jcr:content/root/responsivegrid/contentfragment
But rewriting the following query to
path=/content/we-retail/language-masters/en
1_property=jcr:content/root/responsivegrid/contentfragment/displayMode
1_property.operation=exists
2_property=jcr:content/root/responsivegrid/contentfragment/displayMode
2_property.value=singleText
results in
/content/we-retail/language-masters/en/experience/wester-australia-by-camper-van
/content/we-retail/language-masters/en/experience/arctic-surfing-in-lofoten
/content/we-retail/language-masters/en/experience/steelhead-and-spines-in-alaska
/content/we-retail/language-masters/en/experience/hours-of-wilderness
/content/we-retail/language-masters/en/experience/skitouring
/content/we-retail/language-masters/en/experience/fly-fishing-the-amazon

Related

AEM Querybuilder - How to return only the folders under a path?

I'm trying to rerun only the folders from a given path using query builder on AEM
Query:
path=/content/dam/we-retail/en
type=sling:OrderedFolder
p.hits=selective
p.nodedepth=1
p.limit=-1
Or URL http://localhost:4502/bin/querybuilder.json?p.hits=selective&p.limit=-1&p.nodedepth=1&path=%2fcontent%2fdam%2fwe-retail%2fen&type=sling%3aOrderedFolder
The query returns 35 records, while there are only 6 folders under /content/dam/we-retail/en. How can i return only these 6?
If you are looking at returning only the direct children under a path, use the property path.flat=true.
path=/content/dam/we-retail/en
path.flat=true
type=sling:OrderedFolder
p.hits=selective
p.nodedepth=1
p.limit=-1
However, it is better to loop through the child nodes and identify the folders rather than querying in cases like this where you need only the direct children.
More about the Path Predicate Evaluator here.

AEM CQ5 Query Builder: How to get result by searching for 2 different values in same property?

I want to get result matches with all nodes contains property 'abc' value as 'xyz' or 'pqr'.
I am trying in below ways:
http://localhost:4502/bin/querybuilder.json?path=/content/campaigns/asd&property=abc&property.1_value=/%xyz/%&property.2_value=/%pqr/%property.operation=like&p.limit=-1&orderby:path
http://localhost:4502/bin/querybuilder.json?path=/content/campaigns/asd&property=abc&property.1_value=/%xyz/%&property.2_value=/%pqr/%&property.1_operation=like&property.2_operation=like&p.limit=-1&orderby:path
http://localhost:4502/bin/querybuilder.json?path=/content/campaigns/asd&1_property=abc&1_property.1_value=/%xyz/%&1_property.1_operation=like&2_property=abc&1_property.1_value=/%xyz/%&2_property.1_operation=like&p.limit=-1&orderby:path
But none of them served my purpose. Any thing that I am missing in this?
The query looks right and as such should work. However if it is just xyz or pqr you would like to match in the query, you may not need the / in the values.
For eg.
path=/content/campaigns/asd
path.self=true //In order to include the current path as well for searching
property=abc
property.1_value=%xyz%
property.2_value=%abc%
property.operation=like
p.limit=-1
Possible things which you can check
Check if the path that you are trying to search contains the desired nodes/properties.
Check if the property name that you are using is right.
If you want to match exact values, you can avoid using the like operator and remove the wild cards from the values.
You can actually use the 'OR' operator in your query to combine two or more values of a property.
For example in the query debug interface : http:///libs/cq/search/content/querydebug.html
path=/content/campaigns/asd
property=PROPERTY1
property.1_value=VALUE1
property.2_value=VALUE2
property.operation=OR
p.limit=-1
It worked with below query:
http://localhost:4502/bin/querybuilder.json?orderby=path
&p.limit=-1
&path=/content/campaigns
&property=jcr:content/par/nodeName/xyz
&property.1_value=pqr
&property.2_value=%abc%
&property.operation=like
&type=cq:Page
Note: property name should be fully specified form the type of node we are expecting.
Ex: jcr:content/par/nodeName/xyz above instead of just xyz

The provided start does not map to a value

I have a traversal as follows:
g.V().hasLabel("demoUser")
.as("demoUser","socialProfile","followCount","requestCount")
.select("demoUser","socialProfile","followCount","postCount")
.by(__.valueMap())
.by(__.out("socialProfileOf").valueMap())
.by(__.in("followRequest").hasId(currentUserId).count())
.by(__.outE("postAuthorOf").count())
I'm trying to select a user vertex, their linked social profile vertex, and some other counts. The issue is that all users may not have a socialProfile edge. When this is the case the traversal fails with the following error:
The provided start does not map to a value: v[8280]->[TitanVertexStep(OUT,[socialProfileOf],vertex), PropertyMapStep(value)]
I did find this thread from the gremlin team. I tried wrapping the logic inside of .by() with a coalesce(), and also appending a .fold() to the end of the statement with no luck.
How do I make that selection optional? I want to select a socialProfile if one exists, but always select the demoUser.
coalesce is the right choice. Let's assume that persons in the modern graph have either one or no project associated with them:
gremlin> g.V().hasLabel("person").as("user","project").
select("user","project").by("name").by(coalesce(out("created").values("name"),
constant("N/A")))
==>{user=marko, project=lop}
==>{user=vadas, project=N/A}
==>{user=josh, project=ripple}
==>{user=peter, project=lop}
Another way would be to completely exclude it from the result:
g.V().hasLabel("person").as("user","project").choose(out("created"),
select("user","project").by("name").by(out("created").values("name")),
select("user").by("name"))
But obviously this will only look good if each branch returns a map / selects more than 1 thing, otherwise you're going to have mixed result types.

How do I add a 'where not' to a QueryBuilder Query

I want to search the entire content tree but not specific tress that have a 'Do Not Search' property at their base.
The Query Builder API page does not reference anything besides AND and OR.
Is it possible to exclude paths from the search or can I only explicitly include paths?
The first three lines are "/content AND /content/path/es". I want "/content AND NOT(/content/path/es)"
map.put("group.1_path", "/content");
map.put("group.2_path", "/content/path/es");
map.put("group.p.or","false");
I have tried the next two both true and false and they have no effect.
map.put("group.2_path.p.not", "true");
map.put("group.2_path.not", "true");
map.put("group.2_path", "not('/content/path/es')");
I can't find any documentation that mentions any other name that 'not' or '!' might be used instead.
Yes it is possible. But not exactly in the way you are trying.
You can exclude the pages with certain properties using the property predicate evaluator.
For ex. If you want to exclude pages which have the property "donotsearch" in its jcr:content node, then you can query it using property operation as exists
map.put("path", "/content/geometrixx/en/toolbar");
map.put("type", "cq:Page");
/* Relative path to the property to check for */
map.put("property", "jcr:content/donotsearch");
/* Operation to perform on the value of the prop, in this case existence check */
map.put("property.operation", "exists");
/* Value for the prop, false = not, by default it is true */
map.put("property.value", "false");
This would result in the following XPath Query
/jcr:root/content/geometrixx/en/toolbar//element(*, cq:Page)
[
not(jcr:content/#donotsearch)
]
But in case you would like to exclude pages with certain value for the property donotsearch, then you can change the above query as shown below
map.put("property", "jcr:content/donotsearch"); //the property to check for
map.put("property.operation", "equals"); // or unequals or like etc..
map.put("property.value", "/*the value of the property*/");
You can find a lot other info regarding querying by referring to the docs.
I'm not sure what version of CQ you're using (you linked to the 5.4 docs), but in 5.5 and above, the PredicateGroup class has a setNegated method to exclude results that would match the group defined.
You can't set negation on an individual Predicate, but there would be nothing to stop you creating a group with just the predicate that you wish to negate:
Predicate pathPredicate = new Predicate("path").set("path", "/content/path/es");
PredicateGroup doNotSearchGroup = new PredicateGroup();
doNotSearchGroup.setNegated(true);
doNotSearchGroup.add(pathPredicate);
Query query = queryBuilder.createQuery(doNotSearchGroup);
EDIT: Just to update in relation to your comment, you should be able to add a PredicateGroup to another PredicateGroup (as PredicateGroup is a subclass of Predicate). So once you have your negated group, combine it with the path search:
Predicate pathPredicate = new Predicate("path");
pathPredicate.set("path", "/content");
PredicateGroup combinedPredicate = new PredicateGroup();
combinedPredicate.add(pathPredicate);
combinedPredicate.add(doNotSearchGroup);
Query query - queryBuilder.createQuery(combinedPredicate);
It is pretty straightforward implementation.
Use
map.put("group.p.not",true)
map.put("group.1_path","/path1/where/you/donot/want/to/search")
map.put("group.2_path","/path2/where/you/donot/want/to/search")
I've run into the same problem and while I couldn't fully solve it I was able to come up with a workaround using groups and the unequals operator. Something like:
path=/var/xxx
1_property=jcr:primaryType
1_property.value=rep:ACL
1_property.operation=unequals
2_property=jcr:primaryType
2_property.value=rep:GrantACE
2_property.operation=unequals
Btw, map.put("group.p.not",true) did not work for me.
This link has a lot of useful information: https://hashimkhan.in/2015/12/02/query-builder/

extjs 4 tree select a specific node by its internal id (not by record index)

I'm trying to sync a dataview (explorer window) with a tree (directory tree).
When I click on an element on my dataview, I'd like the same node gets selected on the tree
The problem is that using the
tree.getSelectionModel().select(index)
doesn't allow me to select the node by its internal id (the id I provided in my treestore), but only by the record index...
So I just can't sync both views...
There would be the solution of the expandPath(), but my treestore is fed by a relational database (id,name,parent_id etc..), so finding the full path is(or could be) a heavy load for the server (I'd like to avoid to have to provide any path...).
Basically I would like to be able to say "expand the node where the "id= " (or any other key/value of the treestore).
Is it possible ? Is there any workaround ?
Thank you for reading me !
The tree.getSelectionModel().select(record) function can accept a record instance instead of an index. I would do something like this:
var record = tree.getRootNode().findChild('id_name','record_id',true);
tree.getSelectionModel().select(record);
for more info on the findChild function, check out the NodeInterface docs here:
http://docs.sencha.com/ext-js/4-0/#/api/Ext.data.NodeInterface-method-findChild
you can also use selecteditemtree.data.id for this.