So I have a fairly complex section structure that (on an Entry Type) has a matrix field that contains entries as fields(sub-entry) within a blocktype.
I'd like to write a GraphQL query such that when text is matched on a field in the sub-entry on the matrix blocktype to return the entire section entry. I have thus far only been able to return matches on the title of the sub-entry. When I search for text on a custom field within the sub-entry nothing is returned. I do have the Use this field’s values as search keywords
option checked on the matrix field of the main entry, and the custom fields on the sub-entry checked as well. I also went poking around the database in the searchindex
table and I can see the field values/keywords in there for the sub-entry I created.
Here is the query I've been playing around with:
fragment tour on tours_tour_Entry {
title
... on tours_tour_Entry {
title
tourVariety
duration
complexity
thumbnail {
url
}
backgroundImage {
url
}
introHeading
introSubheading
introContentBlocks {
... on introContentBlocks_introBlock_BlockType {
body
}
}
factsHeading
factsContentBlocks {
... on factsContentBlocks_factsContentBlock_BlockType {
body
}
}
tourPois {
... on tourPois_tourPoi_BlockType {
title
description
poi {
title
... on pois_poi_Entry {
fov
description
astroObjects {
... on astroObjects_astroObject_Entry {
ra
dec
image {
url
}
characteristics
}
}
}
}
}
}
}
}
fragment poi on pois_poi_Entry {
fov
description
astroObjects {
... on astroObjects_astroObject_Entry {
ra
dec
image {
url
}
characteristics
}
}
}
fragment astroObject on astroObjects_astroObject_Entry {
ra
dec
image {
url
}
characteristics
}
{
entries(search: "*desc* OR *char*") {
...tour
...poi
...astroObject
}
}
When I perform this search, the fragments for "poi" and "astroObject" return results, but not "tour". What am I doing wrong in the query or in the "tour" fragment"? Is this even possible?
Edit based on Andris's answer:
(Including all the relevant code for posterity)
Okay, so I've created a custom plugin that extends the relevant classes and I'm still not able to get entries as results - which is odd considering that I am getting IDs back from my custom query.
Plugin.php
<?php
namespace edr;
use Craft;
use edr\queries\EntryAsField;
use edr\arguments\EntryAsFieldArgumentHandler;
use craft\events\RegisterGqlQueriesEvent;
use craft\services\Gql;
use yii\base\Event;
use craft\gql\ArgumentManager;
use craft\events\RegisterGqlArgumentHandlersEvent;
class Plugin extends \craft\base\Plugin {
public static $plugin;
public $hasCpSettings = true;
public function init() {
parent::init();
self::$plugin = $this;
$this->registerArgumentHandler();
$this->registerQuery();
}
protected function createSettingsModel() {
return new \edr\models\Settings();
}
protected function registerArgumentHandler() {
Event::on(
ArgumentManager::class,
ArgumentManager::EVENT_DEFINE_GQL_ARGUMENT_HANDLERS,
function(RegisterGqlArgumentHandlersEvent $event) {
$event->handlers["searchRelated"] = EntryAsFieldArgumentHandler::class;
}
);
}
protected function settingsHtml() {
return \Craft::$app->getView()->renderTemplate(
'edr-nested-entry-query/settings',
[ 'settings' => $this->getSettings() ]
);
}
public function registerQuery() {
Event::on(
Gql::class,
Gql::EVENT_REGISTER_GQL_QUERIES,
function(RegisterGqlQueriesEvent $event) {
$event->queries['nestedEntries'] = EntryAsField::getQueries();
}
);
}
}
EntryAsField.php
<?php
namespace edr\queries;
use edr\arguments\EntryAsFieldArguments;
use craft\gql\arguments\elements\Entry as EntryArguments;
use craft\gql\base\Query;
use craft\gql\interfaces\elements\Entry as EntryInterface;
use craft\gql\resolvers\elements\Entry as EntryResolver;
use craft\helpers\Gql as GqlHelper;
use GraphQL\Type\Definition\Type;
class EntryAsField extends \craft\gql\base\Query
{
public static function getQueries($checkToken = true): array
{
if ($checkToken && !GqlHelper::canQueryEntries()) {
Craft::info("platypus");
return [];
}
return [
'type' => Type::listOf(EntryInterface::getType()),
'args' => EntryAsFieldArguments::getArguments(),
'resolve' => EntryResolver::class . '::resolve',
'description' => 'This query is used to query for entries.',
'complexity' => GqlHelper::relatedArgumentComplexity(),
];
}
}
EntryAsFieldArguments.php
<?php
namespace edr\arguments;
use GraphQL\Type\Definition\Type;
use craft\gql\types\QueryArgument;
use craft\gql\types\input\criteria\Entry;
class EntryAsFieldArguments extends \craft\gql\base\ElementArguments
{
public static function getArguments(): array
{
return array_merge(parent::getArguments(), self::getContentArguments(), [
'searchRelated' => [
'name' => 'searchRelated',
'type' => Type::listOf(Entry::getType()),
'description' => 'Matches search on entries-as-fields and returns the whole entry.'
],
]);
}
}
EntryAsFieldArgumentHandler.php
<?php
namespace edr\arguments;
use Craft;
use craft\elements\Entry;
use craft\gql\base\RelationArgumentHandler;
use craft\elements\MatrixBlock;
class EntryAsFieldArgumentHandler extends RelationArgumentHandler
{
protected $argumentName = 'searchRelated';
protected function handleArgument($argumentValue)
{
Craft::info("bobcat");
$argumentValue = parent::handleArgument($argumentValue);
$ids = $this->getIds(Entry::class, $argumentValue);
$relatedIds = MatrixBlock::find()->select('ownerId')->column();
if(count($relatedIds) > 0) { // dedupe and stuff in 2d array
$relatedIds = [array_unique($relatedIds)];
}
Craft::info("nested-entries-graphql-queries - DEBUG - Returned IDs from 1st query");
Craft::info($ids);
Craft::info("nested-entries-graphql-queries - DEBUG - Returned IDs from 2nd queryz");
Craft::info($relatedIds);
return $relatedIds;
}
}
In the argument handler above, the first query to getIDs() returns IDs fine. The MatrixBlock query to get the ownerIDs also returns IDs fine and I return these IDs as a 2d array. I get no results from this query though - am I missing something?
Query:
{
nestedEntries(searchRelated: [{search: "*out*"}]) {
id
title
}
}