Jump to content
PeterDK

FieldType Cache - please elaborate

Recommended Posts

Hi,

I just installed a fresh processwire install and I see a FieldType Cache. The 'summary' tells me: "Caches the values of other fields for fewer runtime queries. Can also be used to combine multiple text fields and have them all be searchable under the cached field name."

I cannot see where or how I can 'combine multiple text fields'. In the UI i can only select some fields, but there is no way to 'combine' them.

Could someone point me to some practical uses of this Field?

Share this post


Link to post
Share on other sites

I'm not exactly sure what you're thinking "combine" means here, but this field does exactly what the description says; it grabs data from other fields, mashes it all together into one big blob of (JSON) content -- and that's just about it.

One very simple (yet sometimes very practical) use case is if you've got, say, 15 different text fields and you need to find pages that contain value "john doe" in any of those. Instead of doing this:

$john_does = $pages->find('field1|field2|field3|field4|field5|...|field15%="john doe"');

.. you can create a cache field, select all of those fields to be cached in it, and then do this:

$john_does = $pages->find('my_cache_field%="john doe"');

Not only does this look clean, in certain situations it can wildly improve query performance.

  • Like 18

Share this post


Link to post
Share on other sites

I'm not exactly sure what you're thinking "combine" means here, but this field does exactly what the description says; it grabs data from other fields, mashes it all together into one big blob of (JSON) content -- and that's just about it.

One very simple (yet sometimes very practical) use case is if you've got, say, 15 different text fields and you need to find pages that contain value "john doe" in any of those. Instead of doing this:

$john_does = $pages->find('field1|field2|field3|field4|field5|...|field15%="john doe"');

.. you can create a cache field, select all of those fields to be cached in it, and then do this:

$john_does = $pages->find('my_cache_field%="john doe"');

Not only does this look clean, in certain situations it can wildly improve query performance.

Under this scenario for improving query performance, I'm wondering this filetype cache file should be hidden from users.

Am I right ?

Share this post


Link to post
Share on other sites

Hi Guys

Do you perhaps know, if this fieldtype is also capable of searching through all repeater/pagetable/page fields when I am referencing one of these fieldtypes inside the field options of a cache field?

Share this post


Link to post
Share on other sites
2 hours ago, Nukro said:

Do you perhaps know, if this fieldtype is also capable of searching through all repeater/pagetable/page fields when I am referencing one of these fieldtypes inside the field options of a cache field?

I'm pretty sure Page fields are only stored as IDs in a cache field, and I expect Repeaters and PageTables would be the same. Which greatly decreases the usefulness of cache fields. Ryan has said this:

Quote

However, over time I've found the value of this module to be kind of limited, as the potential performance benefits of what it does have not turned out to be nearly as good as I had originally assumed when it was built (5+ years ago). FieldtypeCache essentially duplicates the ProcessWire 1.x storage method. In PW3, I think the time has come to drop this module from the core given how rarely it is used and how limited its benefits have turned out to be.

 

Share this post


Link to post
Share on other sites

Thanks for your clarification @Robin S

I'm asking because I am using this module right now for text and textarea fields for my sitewide search. At the moment I am using two methods to build my search. 

The first method is a hook inside saveReady which renders the actual page and cleans it's content from html and writes it inside a textarea field called "index" which I had created and assigend to the corresponding template/page. This works very good and in my search.php my selector looks like this: 

$siteSelector = "index*=$q, numChildren=0";

 

But there is a problem with this approach. Many of the detail pages on my site are using urlSegments to render it's content. And I don't know how I should render the views for the detail pages since they are not physically pages rather rendered dynamically through urlSegments. So I come up with the FieldtypeCache which collects the content of the specified fields and make it searchable by 1 field.

Perhaps I should change the Hook and should not render the views rather prepare the content of every field in the page and save it inside the index field. This is probably also more consistent and easier to maintain then to have two endpoints I need to take care off.

Share this post


Link to post
Share on other sites

Just curious: do you need this index field to achieve some functionality or are you using it to optimise search performance? Just wondering why you wouldn't include all the fields you want to search in your selector instead of merging fields into the index field.

In terms of dealing with the URL segments, I suppose if you have a detail view that uses a /detail/ URL segment and you think that is the view the visitors will want then you could append /detail/ to the link hrefs in search results for pages with that template.

Share this post


Link to post
Share on other sites
9 hours ago, Robin S said:

Just curious: do you need this index field to achieve some functionality or are you using it to optimise search performance? Just wondering why you wouldn't include all the fields you want to search in your selector instead of merging fields into the index field.

In terms of dealing with the URL segments, I suppose if you have a detail view that uses a /detail/ URL segment and you think that is the view the visitors will want then you could append /detail/ to the link hrefs in search results for pages with that template.

I am using this index field because there are many many fields. And with many many fields I also mean pagetables, repeaters, lot of pagefields and options fields. Most of them is for the controlled output which makes it harder to define which fields I should search inside my search.php. So I decided to go this way, since It will search anything that is visible/rendered on a page and this erase the step to define which fields I should intelligently include in my search so that it would return good search results. Because of this I also abandoned the idea to change the actual method with the one where I loop through all fields and prepare them, since every template has a lot of other complexity and purpose. It just would take to much time to consider all this factors within the search query since I would need to update the code every time a new field or new complexity are added to the template output. 

For the urlSegments I have thinked of giving some arguments to the render method like this:

protected function hookIndexingBefore( HookEvent $event ) {

        $page = $event->arguments("page");

        if(!$page->template->hasField("index")) return;	// no index field in this page/template
        if($page->isNew() || $page->isTrash()) return;

        $language = $this->wire("user")->language;    // save user lang
        $page->index = '';
		
		if($page->template->name == "jobs"){
			//the page is a detail page so render the partial file with some options
			$filepath = "templates/partials/jobs-detail.php";
			$options = array("pagename" => $page->name); 
		}else{
			// render the page with its own template
			$filepath = "";
		}

        foreach($this->wire("languages") as $lang) {

            $this->wire("user")->language = $lang; // change user lang

            wire('pages')->setOutputFormatting(true);
            $content = $page->render($filepath, $options);
            wire('pages')->setOutputFormatting(false);

            if($content) $content = $this->parseContent($content);
            $page->index .= $content;
        }
    
        $this->wire("user")->language = $language; // restore user language
}

And the inside the partial file at the moment I have this:

<?php 
	if($urlsegment){
		$urlpage = $pages->get("name=$urlsegment");
	}
?>
markup ....

 I need to add this so it also works with the hooks above:

<?php 
	// check if detail page is accessd and rendered in normal way
	if($urlsegment){
		$urlpage = $pages->get("name=$urlsegment");
	}

	// page is render via page->render() method from the saveReady Hook
	if($options['pagename']){
		$urlpage = $pages->get("name=".$options['pagename']);
	}
?>

markup...

Don't know if this will work have to try this.

 

Greetings Orkun

Share this post


Link to post
Share on other sites

Got it working by creating a template file for the detail pagetemplate with this code inside:

$out .= wireRenderFile("partials/jobs-detail.php", array(
					   'urlsegment' => $options['pagename'],
					));

 

Removed this other code from the jobs-detail.php file:

if($options['pagename']){
		$urlpage = $pages->get("name=".$options['pagename']);
	}

 

And also changed the hook: 

if($page->template->name == "jobs"){
		$options = array("pagename" => $page->name); 
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...