How can I filter an FlowQuery

Hey guys,

I have build a search plugin, but now I can’t filter all nodes with property “hidesearch”: true.
I have tried this with the outcommented line.

$flowQuery = new FlowQuery(array($node));
                //$flowQuery = (new FlowQuery(array($node)))->filter('[hidesearch = true]')->sort('_index', 'DESC');
                $documentNode = $flowQuery->closest('[instanceof Neos.Neos:Document]')->get(0);
                if (isset($searchNode)) {
                    $results[] = array('searchNode' => $searchNode, 'documentNode' => $documentNode);
                }

Thank you for your answer!

The commented line tries to filter a collection of a single node. That does not make much sense. In general filter works like this but you have to pass a list of nodes that shall be filtered.

Regards, Martin

Thank you. How could I do this?

We’d need a little additional context here to answer this. In your search plugin, there must be a place where you receive an array of all nodes that are searched, no? This would be the place where you can do new FlowQuery($yourNodeArray)->…

Having said that, however, I doubt that doing a live filtering of those nodes will yield the search performance you want. Any reason why you’re not relying on an existing search plugin like Flowpack.SimpleSearch?

In genreal filter is applied to the flowQueryContext.

if you already have a list of nodes you can do this like this.

$flowQuery = new FlowQuery([$node1, $node2, ...]);
$filteredNodes = $flowQuery->filter('[hidesearch = true]')->get();

If you have a starting point and want to find all documents below that match your criterea you can do

$flowQuery = new FlowQuery([$startingNode]);
$filteredNodes = $flowQuery
   ->find('[instanceof Neos.Neos:Document]')
   ->filter('[hidesearch = true]')
   ->get();

This will first find all Documents below the $startingNode and then apply the filter. The two opertions find() and filter() return a new modified flowQueryContext while get() will return the content of the context for use outside of flowQuery.

As @beheist commented that is probably not the ideal way to search across many nodes. It does not provide a fulltext index and the performance will drop if you query too much nodes. So use such a solution only if you have a good reason to assume that the number of nodes you are filtering will not increase too much over time.

Okay thank you. But I have tried this (Commented lines). I get Error 500 :frowning:

$results = array();
        foreach ($nodes as $node) {
            $properties = $node->getProperties();
            foreach ($properties as $propertyName) {
                if (!is_object($propertyName) && is_string($propertyName)) {
                    $searchNode = strip_tags($propertyName);
                }
            }
            if ($node !== NULL && (string) $node->getNodeType() !== 'Neos.Neos:Document') {
                $flowQuery = new FlowQuery(array($node));
                //$flowQuery = (new FlowQuery(array($node)))->filter('[hidesearch = true]')->sort('_index', 'DESC');
                //$filteredNodes = $flowQuery->filter('[hidesearch = false]')->get();
                $documentNode = $flowQuery->closest('[instanceof Neos.Neos:Document]')->get(0);
                if (isset($searchNode)) {
                    $results[] = array('searchNode' => $searchNode, 'documentNode' => $documentNode);
                }
            }
        }

You still add only one node to the context. You have to specify the nodes you want to filter first. The code you commented out tries to filter a list that contains a single node.

When working with flowQuery you can start with a single expression and add traversing and filtering step by step.

If you want to check a node against conditions take look at the is() operation. This one will return Boolean true if the condition is matched.