@@ -68,13 +68,6 @@ class ElasticSearchQueryBuilder implements QueryBuilderInterface, ProtectedConte
6868 */
6969 protected $ unsupportedFieldsInCountRequest = array ('fields ' , 'sort ' , 'from ' , 'size ' , 'highlight ' , 'aggs ' , 'aggregations ' );
7070
71- /**
72- * Amount of total items in response without limit
73- *
74- * @var integer
75- */
76- protected $ totalItems ;
77-
7871 /**
7972 * This (internal) array stores, for the last search request, a mapping from Node Identifiers
8073 * to the full ElasticSearch Hit which was returned.
@@ -85,12 +78,6 @@ class ElasticSearchQueryBuilder implements QueryBuilderInterface, ProtectedConte
8578 */
8679 protected $ elasticSearchHitsIndexedByNodeFromLastRequest ;
8780
88- /**
89- * This (internal) array stores all aggregation results for the last search request
90- *
91- * @var array
92- */
93- protected $ elasticSearchAggregationsFromLastRequest ;
9481
9582 /**
9683 * The ElasticSearch request, as it is being built up.
@@ -148,6 +135,13 @@ class ElasticSearchQueryBuilder implements QueryBuilderInterface, ProtectedConte
148135 'fields ' => array ('__path ' )
149136 );
150137
138+
139+ /**
140+ * @var array
141+ */
142+ protected $ result = array ();
143+
144+
151145 /**
152146 * HIGH-LEVEL API
153147 */
@@ -342,7 +336,7 @@ public function lessThanOrEqual($propertyName, $value) {
342336 */
343337 public function queryFilter ($ filterType , $ filterOptions , $ clauseType = 'must ' ) {
344338 if (!in_array ($ clauseType , array ('must ' , 'should ' , 'must_not ' ))) {
345- throw new QueryBuildingException ('The given clause type " ' . $ clauseType . '" is not supported. Must be one of "mmust ", "should", "must_not". ' , 1383716082 );
339+ throw new QueryBuildingException ('The given clause type " ' . $ clauseType . '" is not supported. Must be one of "must ", "should", "must_not". ' , 1383716082 );
346340 }
347341 return $ this ->appendAtPath ('query.filtered.filter.bool. ' . $ clauseType , array ($ filterType => $ filterOptions ));
348342 }
@@ -518,7 +512,9 @@ public function log($message = NULL) {
518512 * @return integer
519513 */
520514 public function getTotalItems () {
521- return $ this ->totalItems ;
515+ if (array_key_exists ('total ' , $ this ->result )) {
516+ return (int ) $ this ->result ['total ' ];
517+ }
522518 }
523519
524520 /**
@@ -551,7 +547,7 @@ public function getFullElasticSearchHitForNode(NodeInterface $node) {
551547 /**
552548 * Execute the query and return the list of nodes as result.
553549 *
554- * This method is rather internal; just to be called from the ElasticSearchQueryResult. For the public API, please use execute()
550+ * This method is rather internal; just to be called from the ElasticSearchQueryResult. For the public API, please use execute()
555551 *
556552 * @return array<\TYPO3\TYPO3CR\Domain\Model\NodeInterface>
557553 */
@@ -560,65 +556,20 @@ public function fetch() {
560556 $ response = $ this ->elasticSearchClient ->getIndex ()->request ('GET ' , '/_search ' , array (), json_encode ($ this ->request ));
561557 $ timeAfterwards = microtime (TRUE );
562558
563- $ treatedContent = $ response ->getTreatedContent ();
564- $ hits = $ treatedContent ['hits ' ];
565-
566- if ($ this ->logThisQuery === TRUE ) {
567- $ this ->logger ->log ('Query Log ( ' . $ this ->logMessage . '): ' . json_encode ($ this ->request ) . ' -- execution time: ' . (($ timeAfterwards - $ timeBefore ) * 1000 ) . ' ms -- Limit: ' . $ this ->limit . ' -- Number of results returned: ' . count ($ hits ['hits ' ]) . ' -- Total Results: ' . $ hits ['total ' ], LOG_DEBUG );
568- }
569-
570- $ this ->totalItems = $ hits ['total ' ];
571-
572- if ($ hits ['total ' ] === 0 ) {
573- return array ();
574- }
575-
576- $ nodes = array ();
577- $ elasticSearchHitPerNode = array ();
559+ $ this ->result = $ response ->getTreatedContent ();
578560
579- /**
580- * TODO: This code below is not fully correct yet:
581- *
582- * We always fetch $limit * (numerOfWorkspaces) records; so that we find a node:
583- * - *once* if it is only in live workspace and matches the query
584- * - *once* if it is only in user workspace and matches the query
585- * - *twice* if it is in both workspaces and matches the query *both times*. In this case we filter the duplicate record.
586- * - *once* if it is in the live workspace and has been DELETED in the user workspace (STILL WRONG)
587- * - *once* if it is in the live workspace and has been MODIFIED to NOT MATCH THE QUERY ANYMORE in user workspace (STILL WRONG)
588- *
589- * If we want to fix this cleanly, we'd need to do an *additional query* in order to filter all nodes from a non-user workspace
590- * which *do exist in the user workspace but do NOT match the current query*. This has to be done somehow "recursively"; and later
591- * we might be able to use https://github.com/elasticsearch/elasticsearch/issues/3300 as soon as it is merged.
592- */
593- foreach ($ hits ['hits ' ] as $ hit ) {
594- // with ElasticSearch 1.0 fields always returns an array,
595- // see https://github.com/Flowpack/Flowpack.ElasticSearch.ContentRepositoryAdaptor/issues/17
596- if (is_array ($ hit ['fields ' ]['__path ' ])) {
597- $ nodePath = current ($ hit ['fields ' ]['__path ' ]);
598- } else {
599- $ nodePath = $ hit ['fields ' ]['__path ' ];
600- }
601- $ node = $ this ->contextNode ->getNode ($ nodePath );
602- if ($ node instanceof NodeInterface) {
603- $ nodes [$ node ->getIdentifier ()] = $ node ;
604- $ elasticSearchHitPerNode [$ node ->getIdentifier ()] = $ hit ;
605- if ($ this ->limit > 0 && count ($ nodes ) >= $ this ->limit ) {
606- break ;
607- }
608- }
561+ $ this ->result ['nodes ' ] = array ();
562+ if (array_key_exists ('hits ' , $ this ->result ) && is_array ($ this ->result ['hits ' ]) && count ($ this ->result ['hits ' ]) > 0 ) {
563+ $ this ->result ['nodes ' ] = $ this ->convertHitsToNodes ($ this ->result ['hits ' ]);
609564 }
610565
611566 if ($ this ->logThisQuery === TRUE ) {
612- $ this ->logger ->log ('Query Log ( ' . $ this ->logMessage . ') Number of returned results: ' . count ($ nodes ), LOG_DEBUG );
567+ $ this ->logger ->log (sprintf ('Query Log (%s): %s -- execution time: %s ms -- Limit: %s -- Number of results returned: %s -- Total Results: %s ' ,
568+ $ this ->logMessage , json_encode ($ this ->request ), (($ timeAfterwards - $ timeBefore ) * 1000 ), $ this ->limit , count ($ this ->result ['hits ' ]['hits ' ]), $ this ->result ['hits ' ]['total ' ])
569+ , LOG_DEBUG );
613570 }
614571
615- $ this ->elasticSearchHitsIndexedByNodeFromLastRequest = $ elasticSearchHitPerNode ;
616-
617- if (array_key_exists ("aggregations " , $ treatedContent )) {
618- $ this ->elasticSearchAggregationsFromLastRequest = $ treatedContent ['aggregations ' ];
619- }
620-
621- return array_values ($ nodes );
572+ return $ this ->result ;
622573 }
623574
624575 /**
@@ -633,12 +584,6 @@ public function execute() {
633584 return $ result ;
634585 }
635586
636- /**
637- * @return array
638- */
639- public function getElasticSearchAggregationsFromLastRequest () {
640- return $ this ->elasticSearchAggregationsFromLastRequest ;
641- }
642587
643588 /**
644589 * Return the total number of hits for the query.
@@ -751,4 +696,53 @@ public function query(NodeInterface $contextNode) {
751696 public function allowsCallOfMethod ($ methodName ) {
752697 return TRUE ;
753698 }
699+
700+ /**
701+ * @param array $hits
702+ * @return array Array of Node objects
703+ */
704+ protected function convertHitsToNodes (array $ hits ) {
705+ $ nodes = array ();
706+ $ elasticSearchHitPerNode = array ();
707+
708+ /**
709+ * TODO: This code below is not fully correct yet:
710+ *
711+ * We always fetch $limit * (numerOfWorkspaces) records; so that we find a node:
712+ * - *once* if it is only in live workspace and matches the query
713+ * - *once* if it is only in user workspace and matches the query
714+ * - *twice* if it is in both workspaces and matches the query *both times*. In this case we filter the duplicate record.
715+ * - *once* if it is in the live workspace and has been DELETED in the user workspace (STILL WRONG)
716+ * - *once* if it is in the live workspace and has been MODIFIED to NOT MATCH THE QUERY ANYMORE in user workspace (STILL WRONG)
717+ *
718+ * If we want to fix this cleanly, we'd need to do an *additional query* in order to filter all nodes from a non-user workspace
719+ * which *do exist in the user workspace but do NOT match the current query*. This has to be done somehow "recursively"; and later
720+ * we might be able to use https://github.com/elasticsearch/elasticsearch/issues/3300 as soon as it is merged.
721+ */
722+ foreach ($ hits ['hits ' ] as $ hit ) {
723+ // with ElasticSearch 1.0 fields always returns an array,
724+ // see https://github.com/Flowpack/Flowpack.ElasticSearch.ContentRepositoryAdaptor/issues/17
725+ if (is_array ($ hit ['fields ' ]['__path ' ])) {
726+ $ nodePath = current ($ hit ['fields ' ]['__path ' ]);
727+ } else {
728+ $ nodePath = $ hit ['fields ' ]['__path ' ];
729+ }
730+ $ node = $ this ->contextNode ->getNode ($ nodePath );
731+ if ($ node instanceof NodeInterface) {
732+ $ nodes [$ node ->getIdentifier ()] = $ node ;
733+ $ elasticSearchHitPerNode [$ node ->getIdentifier ()] = $ hit ;
734+ if ($ this ->limit > 0 && count ($ nodes ) >= $ this ->limit ) {
735+ break ;
736+ }
737+ }
738+ }
739+
740+ if ($ this ->logThisQuery === TRUE ) {
741+ $ this ->logger ->log ('Query Log ( ' . $ this ->logMessage . ') Number of returned results: ' . count ($ nodes ), LOG_DEBUG );
742+ }
743+
744+ $ this ->elasticSearchHitsIndexedByNodeFromLastRequest = $ elasticSearchHitPerNode ;
745+
746+ return array_values ($ nodes );
747+ }
754748}
0 commit comments