Search sessions and history

Introduction

The Modern UI supports search sessions, the ability to establish a session that persists with the search user across multiple queries. This capability allows Funnelback to record the search and click history for a user, as well as provide a result shopping basket for the user to retain a set of selected search results.

The user session is established through HTTP cookies. History and result selection are saved in a database. There is one database for a given Funnelback installation, but the data is saved on a per-collection basis, meaning that each collection will have separate search and click history, and separate results selection for a given user.

When sessions are enabled, users are automatically assigned a unique ID which is transmitted with every search query.

Caveats

  • This feature rely on the URL of search results being valid URLs, and identical as their URL in the index. If the URL is rewritten in any way (using a hook script for example) you will need to ensure that the search results URLs passed to the session API calls are the indexed URLs, not the rewritten ones.

Enabling and configuring search sessions

Sessions are enabled with the ui.modern.session parameter. Once enabled, Funnelback will immediately start recording searches and clicks, and allow users to select results.

Enabling this parameter will also record unique user IDs in the query and click logs.

Configuration options

Various parameters can be used to configure the session features. Please consult their individual documentation for more details:

Cookies and identifiers

Enabling sessions will provide each user with a unique ID stored in a cookie.

Performance impacts

To record search history Funnelback needs to contact the session database for every query and this impacts the query response time. The time spent contacting and querying the database will depend on the server configuration, the type of database used and the size of the database. For example, on a standard Linux server with the built-in database engine and a fresh database the overhead is around 20ms per query.

For this reason it’s preferable to not enable the session features until you decide to make use of them in your search results page.

Purging old sessions

The database will grow over time as carts and history events get stored. To purge the session database and only retain the N last day of sessions, a GET call to /maintenance/purge-sessions.json?daysToKeep=N can be made. It’s recommended to make this call at regular intervals to keep the database size under control.

To prevent arbitrary external users to purge the sessions database, this call can only be made from localhost (e.g. http://localhost/s/maintenance/purge-sessions.json)

Using an external database

Funnelback ships with an embedded H2 database to store the user sessions. If you want to use an external database you will need to configure a JNDI datasource in Jetty and initialise a new schema with the required tables.

The following instructions give an overview of the process however some steps will be specific to the external database system type. The example given below is specific to PostgreSQL. Please contact support@funnelback.com for further assistance.

The first step is to configure a new datasource in Jetty:

  • Obtain the relevant JDBC driver JAR for your database. It can be stored anywhere on the Funnelback server. In this example we’ll use $SEARCH_HOME/web/postgresql-9.4-1201.jdbc4.jar

  • Update the Jetty service file to add this new JAR to the classpath:

    • Edit $SEARCH_HOME/services/jetty-webserver.service

    • Add a line wrapper.java.classpath.jdbc=/path/to/search_home/web/postgresql-9.4-1201.jdbc4.jar

  • Create a $SEARCH_HOME/web/conf/customiseJettyServers.groovy as outlined in Configuring Funnelback’s embedded web server with the content below:

  • Restart Jetty

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.*;
import org.eclipse.jetty.plus.jndi.*;
// The following import will be specific to your JDBC database driver.
// Note that it's often preferable to use a connection pool rather than using
// the driver directly
import org.postgresql.ds.PGSimpleDataSource;

def Map<String, Server> customise(Map<String, Server> servers) {

   // Create data source
   def ds = new PGSimpleDataSource()
   ds.user = "user"
   ds.password = "password"
   ds.databaseName = "databaseName"
   ds.serverName = "serverName"
   ds.portNumber = 1234

   // Register the datasource and Hibernate dialect
   // to the JNDI context. The list of available dialects can be found
   // in the Hibernate documentation, e.g. http://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/dialect/package-summary
   new EnvEntry("jdbc/search-session", ds)
   new EnvEntry("jdbc/dialect/search-session", "org.hibernate.dialect.PostgreSQLDialect")

   // A logger might be useful for debugging. The messages will appear in the Jetty log ($SEARCH_HOME/web/logs/jetty.log)
   def logger = Log.getLogger("com.funnelback.jetty.customise")
   logger.info("Configured JNDI datasource")

   return servers;
}

You also need to create a new database with the relevant credentials, and initialise its schema with the Funnelback tables. Those steps are specific to the database system type, but Funnelback provides a script to initialise the required tables in $SEARCH_HOME/bin/setup/update-session-db.groovy. This script needs to be run with Groovy. For example:

cd $SEARCH_HOME
tools/groovy/bin/groovy bin/setup/update-session-db.groovy --help

By default this script will initialise the built-in H2 database. To target your external database you’ll have to set the --driver and --url options, to specify the class of the JDBC driver, and the JDBC url to use to connect to the database. Additionally you need to ensure that your JDBC driver is on the classpath with the -cp option.

This script runs in "dry mode" by default. To actually apply the changes to the database, pass the --apply command line option. See the script help for further details.

A complete command line example is:

cd $SEARCH_HOME
tools/groovy/bin/groovy -cp $SEARCH_HOME/web/postgresql-9.4-1201.jdbc4.jar bin/setup/update-session-db.groovy --driver org.postgresql.Driver --url 'jdbc:postgresql://db-server?user=username&password=password' --apply

The Jetty documentation provides some examples of using a connection pool based on a JDBC url and driver class. They can be converted to the Groovy syntax above to be used in Funnelback.

User interface and API