title: Retrieve AEM Page Properties via Search/QueryBuilder API
body: <p>Is there a way to retrieve data stored as page metadata (Page Properties) stored in a separate JCR node via the QueryBuilder API?</p>
  
  <p>Example:</p>
  
  <p><img src="https://i.stack.imgur.com/VoxXM.png" alt="JCR Tree"></p>
  
  <p>The search results should include the data under ~/article-1/jcr:content/thumbnail. However, the only results I am getting are data under the ~article-1/jcr:content/content (a parsys included on the template).</p>
  
  <p>An example query:</p>
  
  <pre><code>http://localhost:4502/bin/querybuilder.json?p.hits=full&amp;path=/content/path/to/articles
  </code></pre>
  
  <p>Results in (snippet):</p>
  
  <pre><code>{
     "jcr:path":"/content/path/to/articles/article-1",
     "jcr:createdBy":"admin",
     "jcr:created":"Tue Dec 03 2013 16:26:51 GMT-0500",
     "jcr:primaryType":"cq:Page"
  },
  {
     "jcr:path":"/content/path/to/articles/article-1/jcr:content",
     "sling:resourceType":"myapp/components/global/page/productdetail",
     "jcr:lockIsDeep":true,
     "jcr:uuid":"4ddebe08-82e1-44e9-9197-4241dca65bdf",
     "jcr:title":"Article 1",
     "jcr:mixinTypes":[
        "mix:lockable",
        "mix:versionable"
     ],
     "jcr:created":"Tue Dec 03 2013 16:26:51 GMT-0500",
     "jcr:baseVersion":"24cabbda-1e56-4d37-bfba-d0d52aba1c00",
     "cq:lastReplicationAction":"Activate",
     "jcr:isCheckedOut":true,
     "cq:template":"/apps/myapp/templates/global/productdetail",
     "cq:lastModifiedBy":"admin",
     "jcr:primaryType":"cq:PageContent",
     "jcr:predecessors":[
        "24cabbda-1e56-4d37-bfba-d0d52aba1c00"
     ],
     "cq:tags":[
        "mysite:mytag"
     ],
     "jcr:createdBy":"admin",
     "jcr:versionHistory":"9dcd41d4-2e10-4d52-b0c0-1ea20e102e68",
     "cq:lastReplicatedBy":"admin",
     "cq:lastModified":"Mon Dec 09 2013 17:57:59 GMT-0500",
     "cq:lastReplicated":"Mon Dec 16 2013 11:42:54 GMT-0500",
     "jcr:lockOwner":"admin"
  }
  </code></pre>
  
  <p>Search configuration is the out-of-the-box default.</p>
  
  <p>EDIT: Data is returning in JSON, however, is not accessable in the API:</p>
  
  <p>Result:</p>
  
  <pre><code>{
     "success":true,
     "results":2,
     "total":2,
     "offset":0,
     "hits":[
        {
           "jcr:path":"/content/path/to/articles/article-a",
           "jcr:createdBy":"admin",
           "jcr:created":"Tue Dec 03 2013 16:27:01 GMT-0500",
           "jcr:primaryType":"cq:Page",
           "jcr:content":{
              "sling:resourceType":"path/to/components/global/page/productdetail",
              "_comment":"// ***SNIP*** //",
              "thumbnail":{
                 "jcr:lastModifiedBy":"admin",
                 "imageRotate":"0",
                 "jcr:lastModified":"Wed Dec 04 2013 12:10:47 GMT-0500",
                 "jcr:primaryType":"nt:unstructured"
              }
           }
        },
        {
           "jcr:path":"/content/path/to/articles/article-1",
           "jcr:createdBy":"admin",
           "jcr:created":"Tue Dec 03 2013 16:26:51 GMT-0500",
           "jcr:primaryType":"cq:Page",
           "jcr:content":{
              "sling:resourceType":"path/to/components/global/page/productdetail",
              "_comment":"// ***SNIP*** //",
              "thumbnail":{
                 "jcr:lastModifiedBy":"admin",
                 "imageRotate":"0",
                 "fileReference":"/content/dam/path/to/IBMDemo/apparel/women/wsh005_shoes/WSH005_0533_is_main.jpg",
                 "jcr:lastModified":"Mon Dec 09 2013 17:57:58 GMT-0500",
                 "jcr:primaryType":"nt:unstructured"
              }
           }
        }
     ]
  }
  </code></pre>
  
  <p>Implementation code:</p>
  
  <pre><code>searchCriteria.put("path", path);
  searchCriteria.put("type", "cq:Page");
  
  searchCriteria.put("p.offset", offset.toString());
  searchCriteria.put("p.limit", limit.toString());
  searchCriteria.put("p.hits", "full");
  searchCriteria.put("p.properties", "thumbnail");
  searchCriteria.put("p.nodedepth", "2");
  
  PredicateGroup predicateGroup = PredicateGroup.create(searchCriteria);
  Query query = queryBuilder.createQuery(predicateGroup, session);
  SearchResult result = query.getResult();
  
  for (Hit hit : result.getHits()) {
      try {
          ValueMap properties = hit.getProperties();
  
          VFSearchResult res = new VFSearchResult();
  
          res.setUrl(hit.getPath());
          res.setImageUrl((String)properties.get("thumbnail"));
          res.setTags((String[])properties.get("cq:tags"));
          res.setTeaserText((String)properties.get("teaserText"));
          res.setTitle((String)properties.get("jcr:title"));
  
          searchResults.add(res);
      } catch (RepositoryException rex) {
          logger.debug(String.format("could not retrieve node properties: %1s", rex));
      }
  }
  </code></pre>