Simple Search with Migx

I’m trying to show MIGX content in my search results using simplesearch. After much trial and error, I finally got content from MIGX to appear in the results. For those MIGX fields that are not empty, the content is shown in the results. However, it also includes all the MIGX field names if those fields have no content.

In this example I searched for the word “volunteer”. You can see in these results it does indeed find the term but also the surrounding code.

content":“”,“cell_5_link”:“”,“cell_5_link_text”:“”,“row-name”:“volunteer”,“cell_1_image”:“”,“cell_1_image_alt”:“”,“cell_1_headline”:“Volunteer/Intern”,“headline-alignment”:“left”,“cell_1_link”:“”,“cell_1_link_text”:“”,“cell_1_content”:"Volunteers…

This is the call. The MIGX TV is called MultiColumn. This is based on the tutorial found here.

The use of the includeTVList parameter seems to have no bearing on the results–same with our without.

[[!SimpleSearch? &includeTVs=1 &processTVs=1 &includeTVList=MultiColumn &showExtract=1 &extractSource=MultiColumn &extractLength=350]]

Is there a way to show just the terms and it’s surrounding content? Is this even possible?

MODX 3.03,
Migx 3.0.1-beta2

You could render the tv on save into another text tv that you use for simplesearch only something like this:

<?php

/*
Update resource fields when they are saved

trigger on the following system events:
	OnBeforeDocFormSave
	OnDocFormSave

note: changing / inserting tv values is better done onDocFormSave as the process for saving tvs onBeforeDocFormSave is much more complicated (apparently)

*/

$varClassKey 	= $resource->get('class_key');

if( isset($varClassKey) &&  $varClassKey != 'modDocument' ) {
    return;
}

$template_whitlist = [2];

if (in_array($resource->get('template'), $template_whitlist)) {

    $migxJson = $resource->getTVValue(6);
    $migxOutput = $modx->runSnippet('getImageList', array('value' => $migxJson, 'tpl' => 'render_migx-row'));
    $resource->set('content',$migxOutput);
    $resource->save();
}

return;

In this case i render this in content, because i do not use content field. and content is automatically indexed by simple search, but you ge the idea i think,

6 is my migx tv id, but you could also use the tvName there

1 Like

Thanks Dimmy.

That is an interesting approach. It would preclude me from using the content field going forward, but that might be OK in this case.

Can I assume there’s no way to pull processed content from MIGX directly while ignoring the empty fields?

you would need to process the MIGX TV for each resource while searching.
That would be very slow and complicated.
If you need searching, @dimmy s suggestion is the better and easier way.

Or you could store the MIGX items into a custom-table and use a MIGXdb TV instead.
Then you could search within that custom-table.

OK, thanks Bruno. I understand now. Good to know.

Thanks Dimmy for your help!

Hey Dimmy

This isn’t working for me. I created a plugin, changed the tv name to my own and set the system events. When I save the resources, nothing happens.

Any suggestions?

Did you change the line $template_whitlist = [2]; to the ID of your template?
Did you change the template 'tpl' => 'render_migx-row' to an existing chunk on your system?
If you are using MODX 3, you also have to change the class key here → if( isset($varClassKey) && $varClassKey != 'modDocument' ) {


Also, the plugin only needs to run on the event “OnDocFormSave”.

I did change the id of my tv. I just created a chunck called render_migx-row

I am using MODX 3. This line is the same as in Dimmy’s original is it not?

I assume the chunk should be empty? Do I need to add it my template somewhere? Should I be able to see the rendered content in the content field in the resource?

Yes, but you have to change the string 'modDocument' to 'MODX\\Revolution\\modDocument'. (In MODX 3 the class key also contains the namespace MODX\Revolution.)

What chunk? “render_migx-row”?
No, it should contain the placeholders and markup you want to save to the content field.

Yes, if the plugin works correctly, you should see the result from the snippet call “getImageList” using the chunk “render_migx-row” in the content field.

Ah! Got it.

Thank you!

I’m still not getting results from other TVs.

I’ve got two standard TVs; content1, content2 (and others). The results do list the pages with the search term in those fields, but doesn’t show the extract. I’ve stripped out everything except bare essentials try to solve this. I’ve tried listing the TV names but no change. I can see in the results, the html for the extract, but it is empty.

[[!SimpleSearch?
&includeTVs=1
&processTVs=1
&showExtract=1
]]

2023-06-23_14-21-11

I feel like I’m missing something obvious, this seems straight forward in the docs.

The property &extractSource defines from which field the extract gets generated. By default this is the “content” field. So in the extract you only see content from the “content” field.

I’m not sure what you are trying to achieve.

  • If you want to show the whole content from a TV, then the placeholder should be available in the &tpl chunk.
  • If you want to show the extract from the combination of multiple fields, set the &extractSource property to a snippet.
  • If you want that the content from both your TVs (“content1” and “content2”) gets written to the resource’s content field, then change the plugin to read both of them.

This suggests to me that simpleSearch cannot read any TV other then the standard resource fields, pagetitle, content, etc out of the box without jumping through these complicated hoops?

What is the point of these parameters.

&includeTVs=1
&processTVs=1

I don’t mean to be difficult, I’m just trying to understand.

That’s not the case.

When you enter a search term, SimpleSearch searches for this term in the database.
By default it only searches the fields of the table modx_site_content that are defined with the property &docFields.

When you set the property &includeTVs=`1`, SimpleSearch also searches in all the TV values (in the database table modx_site_tmplvar_contentvalues) for the search term. Additionally, the TV values are now available as placeholders in the &tpl property (and can also be used as the source for the extract).

By default, the TV placeholders contain the values exactly as they are stored in the database.
If you set &processTVs=`1`, then the TV values are processed according to the TV settings (Tab “Output Options”). This property affects only the displaying of the search results and not the search itself!


An example:

Let’s say you have a TV with the name “my_tv”, the “Input Type” = Text and the “Output Type” = String (with “String Format” = Upper Case).

The value of the TV is “Foo Bar”.

You search for “foo”.

  • With &includeTVs=`0` &processTVs=`0` this resource is not found.
  • With &includeTVs=`1` &processTVs=`0` the resource is found. The placeholder [[+my_tv]] in &tpl has the value “Foo Bar”.
  • With &includeTVs=`1` &processTVs=`1` the resource is found. The placeholder [[+my_tv]] in &tpl has the value “FOO BAR”.

With a MIGX TV, there is no matching “Output Option” to set in the TV. So setting the property &processTVs to “1” in the snippet call makes no difference.

MIGX stores the data as JSON in the TV table (modx_site_tmplvar_contentvalues). SimpleSearch doesn’t know the type of a TV and treats everything just as a string. If a substring of the JSON matches the search term, then the resource is in the results, otherwise not.


If you want to output the content of your MIGX TV in the search result not as JSON but processed, you have basically 3 options:

  1. Process the TV content in the &tpl chunk with a call to getImageList ([[getImageList? &value=`[[+my_tv]]` &tpl=`some_chunk`]]) to show the whole content.
  2. Set &extractSource to a snippet and run getImageList in the snippet to show an extract from the MIGX TV → return $modx->runSnippet('getImageList', ['value' => $my_tv, 'tpl' => 'some_chunk']);
  3. Process the MIGX TV on save in a plugin and store the result in a resource field or a different TV, so that the already processed TV content can directly be used for the search and the display of the search results.

Finally getting back to this. I’m making progress. I’ve put the placeholders in the searchTpl on the search results page:

<div class="sisea-result">
    <h3>[[+idx]]. <a href="[[+link:is=``:then=`[[~[[+id]]]]`:else=`[[+link]]`]]" title="[[+longtitle]]">[[+pagetitle]]</a></h3>
    <div class="extract"><p>[[+extract]] [[+content1]] [[+content2]] </p></div>
</div>

I’m now getting search results from the two TVs from the pages containing the search terms.

However, the parameters I’ve set don’t seem to have any affect. I’m getting the ALL the content from the TVs, not just an extract, no limits, which is multiple paragraphs of text and images.

[[!SimpleSearch?

&tpl=`searchTpl`
&includeTVs=`1` 
&processTVs=`1 
&showExtract=`1` 
&extractLength=`200`
&highlightResults=`1`
&maxWords=`7`

]]

I appreciate your patience with me on this.

Only the placeholder [[+extract]] contains the extract.
The other placeholders contain the resource and tv values from the database.

If you want an extract from a TV, change the property &extractSource to a different field than the default (which is “content”).
If you want an extract from multiple fields, set &extractSource to the name of a custom snippet where you return a string. For example like this:

<?php
$content1 = $modx->getOption('content1', $scriptProperties, '');
$content2 = $modx->getOption('content2', $scriptProperties, '');
return trim($content1 . ' ' . $content2);