Blogs

Using MoreLike This Component in Solr

May 09, 2013 by Jasgeet Singh

The MLT request handler will give MLT results based on a specific indexed document. This is commonly used in reaction to a user clicking a "more like this" link on existing search results. The key input to this option is a reference to the indexed document that you want similar results for.

MLT Search Component

MLT Parameters

params

Description

mlt

true to enable MoreLikeThis results

mlt.count

The number of similar documents to return for each result.

 

params

Description

mlt.fl

A comma or space separated list of fields to consider in MLT. The interesting terms are searched within these fields only, then each field should ideally have either termVectors or stored set to true in the schema.

mlt.qf

Different field boosts can optionally be specified with this parameter. The fields referenced should also be listed in mlt.fl. If there is a title or similar identifying field, then this field should probably be boosted higher.

mlt.mintf

The minimum number of times a term must be used within a document (across those fields in mlt.fl ) for it to be an interesting term. The default is 2.

mlt.mindf

The minimum number of documents that a term must be used in for it to be an interesting term. It defaults to 5.

mlt.minwl

The minimum number of characters in an interesting term. It defaults to 0.

mlt.maxwl

The maximum number of characters in an interesting term. It defaults to 0.

mlt.maxqt

The maximum number of interesting terms that will be used in an MLT query. It is limited to 25 by default, which is plenty.

mlt.maxntp

The maximum number of tokens to parse in each example doc field that is not stored with TermVector support. It default to 5000.

mlt.boost

This boolean toggles whether or not to boost each interesting term used in the MLT query. It default to false.

 

The MLT request handler needs to be configured in solrconfig.xml.

	<requestHandler name="mlt_tracks" class="solr.MoreLikeThisHandler">

	<lst name="defaults">

	<str name="mlt.fl">category, specialities</str>

	<str name="mlt.mintf">1</str>

	<str name="mlt.mindf">2</str>

	<str name="mlt.boost">true</str>

	</lst>

	</requestHandler>

Configure schema.xml:

  1. <field name="category"  type="textProcessed" indexed="true" stored="false" multiValued="true" termVectors="true"/>
   2. <field name="specialities" type="textProcessed" indexed="true" stored="false" multiValued="true" termVectors="true"/>

 

Solr Query:

This query returns similar documents for each document in the response set. Perhaps this should    be called "MoreLikeThese".

http://localhost:8080/solr/select/?qt=mlt&q=id:11&mlt.fl=category,specialities&fl=id&rows=5

 

 

Using Query Term Completion component in Solr

May 01, 2013 by Jasgeet Singh

Query Term Completion

One of the most effective features of a search user interface is automatic/instant-search or completion of query input in a search input box. It is typically displayed as a drop-down menu that appears automatically after typing.

Via Suggester:

New in Solr 3 is a high-speed approach to implement term completion, called the Suggester. The Suggester principally features the fastest search performance - handful of milliseconds per search at most.

The following request handler definition just for using the Suggester, goes in solrconfig.xml:

	<requestHandler name="/suggest" class="solr.SearchHandler">

	<lst name="defaults">

	<str name="spellcheck">true</str>

	<str name="spellcheck.dictionary">a_suggest</str>

	<str name="spellcheck.onlyMorePopular">true</str>

	<str name="spellcheck.count">5</str>

	<str name="spellcheck.collate">true</str>

	</lst>

	<arr name="components">

	<str>suggest</str>

	</arr>

	</requestHandler>


	<searchComponent name="suggest" class="solr.SpellCheckComponent">

	<lst name="spellchecker">

	<str name="name">a_suggest</str>

	<str name="classname"> org.apache.solr.spelling.suggest.Suggester</str>

	<str name="lookupImpl"> org.apache.solr.spelling.suggest.fst.FSTLookup</str>

	<str name="field">a_spell</str>

	<str name="buildOnOptimize">true</str>

	<int name="weightBuckets">100</int><!-- an FST option -->

	</lst>

	</searchComponent>

spellcheck.onlyMorePopular - this parameter means that the results should be sorted by frequency versus alphabetically almost certainly what is desired.

weightBuckets -  option is specific to FSTLookup which approximates the frequency of the terms it stores into a discrete set of buckets, defaulting to 10. It can range between 1 and 255. Increasing weightBuckets to 100 or more improves the fidelity of the weights, resulting in more relevant suggestions.

Using Highlighting Component in Solr

May 01, 2013 by Jasgeet Singh

Search components must be registered with Solr to be activated so that they can then be referred to in a components list. All of the standard components are pre-registered. Here's an example of how a search component named “elevator” is registered in solrconfig.xml:


<searchcomponent class="solr.QueryElevationComponent" name="elevator"> 
<str name="queryFieldType">string</str> 
<str name="config-file">elevate.xml</str> 
</searchcomponent>

The Highlighting Component

The component is using for returning highlighted text snippets of matching text in the original data.

The following are the parameters observed by the highlighter search component:

• hl: Set to true to enable search highlighting. Without this, the other parameters are ignored, and highlighting is effectively disabled.

	SolrQuery solrQuery = new SolrQuery(“*”)

	solrQuery.setHighlight(true)

• hl.fl: A comma or space separated list of fields that will be highlighted. It is important for a field to be marked as stored in the schema in order to highlight on it. You may use an asterisk wildcard to conveniently highlight on all of the text fields, such as * or r_*. If you use a wildcard, then consider enabling the hl.requireFieldMatch option.

	SolrQuery solrQuery = new SolrQuery(“*”)

	solrQuery.setHighlight(true)

	solrQuery.setHighlightRequireFieldMatch(true)

• hl.snippets: This is the maximum number of highlighted snippets that will be generated per field. It defaults to 1, which you will probably not change. By setting this to 0 for a particular field, you can effectively disable highlighting for that field. You might do that if you used a wildcard for hl.fl and want to make an exception.

	SolrQuery solrQuery = new SolrQuery(“*”)

	solrQuery.setHighlight(true)

	solrQuery.setHighlightSnippets(1)

• hl.fragsize: The maximum number of characters returned in each snippet, measured in characters. The default is 100. If 0 is specified, then the field is not fragmented and whole field values are returned. Obviously, be wary of doing this for large text fields.

	SolrQuery solrQuery = new SolrQuery(“*”)

	solrQuery.setHighlight(true)

	solrQuery.setHighlightSnippets(1)

	solrQuery.setHighlightFragsize(100)

• hl.formatter: Choose how to format the highlighting. This parameter refers to a named <formatter/> element in <highlighting/> in solconfig.xml. The default implementation named html further specifies two more parameters:

° hl.simple.pre and hl.simple.post: This is the text that will    be inserted immediately before and after matched terms in the snippet in order to demarcate them from the surrounding text. Note that the circumstantial presence of whatever values are chosen in the original text, such as HTML with pre-existing emphasis tags, are not escaped, and in rare circumstances may lead to a false highlight.

	SolrQuery solrQuery = new SolrQuery(“*”)

	solrQuery.setHighlight(true)

	solrQuery.setHighlightSimplePre(“before”)

	solrQuery.setHighlightSimplePost(“after”)

Hope it helps!

Using Solr queries in Solr4J

April 29, 2013 by Jasgeet Singh

I learned a few things about using Solr Queries in a project where we used Solr4J and Solr full Text search. I am blogging about some of my learnings on How to use Solr Queries here . If you are not aware about Solr Search Engine, you can read about the same from  link here:

I will start with some examples

Example 1: If we have facet Company Type which has some facet values like Retail, Accommodation, Travels & Construction and facet Specialities. We want the result where all company types must have at least one speciality except Accommodation.

	def solrQuery = new SolrQuery ("*”)

	solrQuery.addField("company_type")

	solrQuery.addField("specialities")

	solrQuery.addFilterQuery("((+category: Retail) AND (specialities: [* TO *])) OR (category :( Accommodation)) OR ((category: Travels) AND (specialities: [* TO *])) OR ((category: Construction) AND (specialities: [* TO *]))")

Example 2: If we want to find search terms not from whole document only from some facets.

	def solrQuery = new SolrQuery ("*”)

	solrQuery.addField ("location")

	solrQuery.addField ("city")

	solrQuery.addField ("country")

	def filterQuery = / (location: "searchTerm"+*) OR (city: "searchTerm"+*) OR (country: "searchTerm"+*)/"

	solrQuery.addFilterQuery (filterQuery)

Here at line no 9, I add “*” with the search term, it means we find the search term from facets containing the words starting with “search terms”. It must to add in order to refine your searching.

Example 3: How to get all facet values that particular facet contains.

	SolrQuery solrQuery = new SolrQuery ("*")

	solrQuery.add("wt","json")

	solrQuery.add("json.nl", "map")

	solrQuery.setRows(0)

	solrQuery.setFacet(true)

	solrQuery.addFacetField("company_type")

From this query you get the JSONObject containing facet company_type as key and its facet values.

Existence (and non-existence) queries:

This is actually not a new syntax case, but an application of range queries. Suppose you wanted to match all of the documents that have an indexed value in a field. Here we find all of the documents that have something in facet Employee_Name:

Employee_Name: [* TO *]

This can be negated to find documents that do not have a value for Employee_Name, as shown in the following code:

- Employee_Name: [* TO *]

 

Hope it helps!

Configuring Grails App for UTF8 Character Encoding

April 17, 2013 by Varun Sharma

Today I'm going to share my findings on how to use UTF-8 character encoding in grails. I had a requirement in one of my projects to use character encoding in my grails application. For that I have made several changes and these are explained below.


1) Changes in DataSource.groovy

url = "jdbc:mysql://localhost:3306/app_name?useUnicode=yes&characterEncoding=UTF-8"
dialect = "com.domain.mysql.dialect.MySQLUTF8InnoDBDialect"


For ex:-
development {
	dataSource {
		dbCreate = "update" // one of 'create', 'create-drop','update'
		url = "jdbc:mysql://localhost:3306/app_name?useUnicode=yes&characterEncoding=UTF-8"
		dialect = "com.domain.mysql.dialect.MySQLUTF8InnoDBDialect"
	}
}

2) Create a new File in src/java/com/domain/mysql/dialect/MySQLUTF8InnoDBDialect.java

    package com.domain.mysql.dialect;
    import org.hibernate.dialect.MySQLInnoDBDialect;
    /**
    * Sets the default charset to UTF-8.
    */
    public class MySQLUTF8InnoDBDialect extends MySQLInnoDBDialect {
    @Override
    public String getTableTypeString() {
    return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
    } 

3) Changes in config.groovy

grails.views.default.codec = "html" // none, html, base64
grails.views.gsp.encoding = "UTF-8"
grails.converters.encoding = "UTF-8"

4) Changes in gsp (I have added this in main.gsp only)

<%@ page contentType="text/html;charset=UTF-8" %>

5) Alter tables with query

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8 
COLLATE utf8_general_ci;

6) Add in server.xml (apache/conf)

Note:- May work without this

 
               URIEncoding="UTF-8" 
               useBodyEncodingForURI="true"

>Hope it helps !

Varun Sharma
varun.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Implementing Reverse Ajax (Comet) in Grails using Websocket and Atmosphere plugin

January 02, 2013 by Nagesh Chauhan

Today I am going to share my findings on how to Integrate websocket in grails using Atmosphere plugin. Initially I just wanted to implement all reverse ajax and server push stuff , so I created a simple servlet based application . Later on I realise that if I could added this in a Grails project than it would be very usefull. After a little effort and a few hour of working I am able to integrate atmosphere with java to take advantage of websocket.

I started all this by creating a simple Grails project in STS. Than I added atmosphere plugin to take advantage of its flexible nature. After this I added some code from sample chat app that is given on atmosphere official site and modified the code according to my need. After a number of failure and retry finaly I was able to see expected result.

I used STS and the default server in it does not support websocket ,so i was forced to add apache tomcat to sts before I start runing my application.

Let me now explain some of code sample and changes that I have implemented to make all this working. Added a simple service to the application that is used to map URL so that js files can attach this to websocket side of code.

\grails-app\services\chat\ChatService.groovy

package oodles.grails.chatApp

import org.atmosphere.cpr.*
import org.atmosphere.cpr.AtmosphereResource.TRANSPORT
import grails.converters.JSON

class GrailsChatService {

    static transactional = false
    static atmosphere = [mapping: '/atmosphere/chatty']

    def onRequest = { event ->
        println "Inside onRequest!"
        try {
            AtmosphereRequest req = event.request
            if (req.method.equalsIgnoreCase("GET")) {
                println 'Suspending'
                event.suspend()
            } else if (req.method.equalsIgnoreCase("POST")) {
                event.broadcaster.broadcast(req.reader.readLine().trim())
            }
        } catch (Exception e) {
            println "ERROR!!!!!"
        }

    }

    def onStateChange = { event ->
        println "Inside onStateChange!"
        AtmosphereResource r = event.resource
        AtmosphereResponse res = r.response

        try {
            if (event.isSuspended()) {
                def msg = JSON.parse(event.message)
                res.writer.write( createMessage(msg.author, msg.message) )

                switch (r.transport()) {
                    case TRANSPORT.JSONP:
                    case TRANSPORT.LONG_POLLING:
                        event.resource.resume()
                        break
                    default:
                        res.writer.flush()
                }
            } else if (!event.isResuming()) {
                event.broadcaster().broadcast( createMessage('someone', 'buh bye') )
            }
        } catch (Exception e) {
            println "ERROR in onStateChange: $e"
        }
    }

    private String createMessage(String author, String text) {
        return new JSON( [text : text, author : author, time : new Date().time] )
    }
}

Methods onStateChange and onRequest handles are responsible for most of the application flow from server to client side. onRequest() is responsible to accept a intial request from browser to send alerts automatically.Once a sse connection is establised all other server push of data is done by onStateChange() , as a notification is received it is sent to browser in form of a message. Application starts from index.gsp ,this file looks something like this :

\grails-app\views\index.gsp

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta name="layout" content="main">
    <title></title

</head>
<body>
<atmosphere:resources/>

<div id="header"><h3>Oodles | Websocket implementation in Grails</h3></div>
<div id="detect"><h3>Websocket Support Status</h3></div>
<div id="content"></div>
<div>
    <span id="status">Connecting...</span>
    <input type="text" id="input"/>
</div>
<div id="header"><h3>Oodles Technologies Pvt Ltd</h3></div>
</body>
</html>

\grails-app\conf\AtmosphereConfig.groovy

atmospherePlugin {
	servlet {

		initParams = [
					'org.atmosphere.cpr.cometSupport': 'org.atmosphere.container.Tomcat7CometSupport'
				]
		urlPattern = '/atmosphere/*'
	}
	handlers {

		atmosphereDotXml = {
		}
	}
}

\web-app\WEB-INF\applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean">
		>description>Grails application factory bean

	<bean id="grailsConfigurator" class="org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator">
		<constructor-arg>
			<ref bean="grailsApplication" />
		</constructor-arg>
		<property name="pluginManager" ref="pluginManager" />
	</bean>

	<bean id="grailsResourceLoader" class="org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean" />

	<bean id="characterEncodingFilter" class="org.springframework.web.filter.CharacterEncodingFilter">
		<property name="encoding">
			<value>utf-8>/value>
		</property>
	</bean>
</beans>

 

\web-app\WEB-INF\atmosphere-decorators.xml

<decorators>
    <excludes>
        <pattern>/atmosphere/*</pattern>
    </excludes>

\web-app\WEB-INF\sitemesh.xml

<sitemesh>
  <page-parsers>
    <parser content-type="text/html" class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser"/>
   <parser content-type="text/html;charset=ISO-8859-1" class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser"/>
    <parser content-type="text/html;charset=UTF-8" class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser"/>
  </page-parsers>
  <decorator-mappers>
    <mapper class="org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper"/>
  </decorator-mappers>
  <excludes file="/WEB-INF/atmosphere-decorators.xml"/>
</sitemesh>

 

Once everything is configured we can get the application running like something like these screens.

In first picture we can check out the status of our server and browser if they support websockts or not . If websocket is supported by the browser than we have to add a name to start chat.

The very first value is used as name and after that all other values are used as a message. First a message is send to the server and after that the server pushes that message to all users.

In last figure we can see that a user named Sridhar is just online and he receives a message from other user Nagesh . This message is a result of server push only as sridhar does not request any message or data from server. Thats all about server push technology that can be implemented in Grails Projects easily.

There are a number of files in a grails project but they all are same and are automatically provided by STS. Here I have added those code files that need to be added explicitly.

 

 

 

 

Hope it helps !

Nagesh Chauhan

www.oodlestechnologies.com

Memcached Integration with Grails

December 03, 2012 by Varun Sharma

"Memcached is free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load."

You can think of it as a short-term memory for your applications.

Installing Memcached:

sudo apt-get install memcached

OR

sudo yum install memcached.

Start Memcached:

After the installation, memcached should already be running. You can check by using the following command

netstat -tap | grep memcached

Usually you will get something like this:

tcp 0 0 localhost:11211 *:* LISTEN 2132/memcached

Note: If it is not running you can start memcached by runnig command:

sudo service memcached start

Using Spymemcached API:

Once your memcached is installed & running you need to use spymemcached API in to your garils application. For that you need to downlaod spymemcached jar (I have used spymemcached-2.7.1.jar)

You need to put spymemcached jar into lib folder of your grails application & configure the build path for the same.

Injecting Memcached into the Grails app:

Once you have the jar file in your application/lib, your next step is to create a Groovy class that will expose the API. Create a service named MemcachedService:

import net.spy.memcached.AddrUtil
import net.spy.memcached.MemcachedClient
import org.springframework.beans.factory.InitializingBean

class MemcachedService implements InitializingBean {

    static final Object NULL = "NULL"
    def MemcachedClient memcachedClient

    def void afterPropertiesSet() {
        memcachedClient = new MemcachedClient(AddrUtil.getAddresses
("localhost:11211"))
    }

    def get(String key) {
        return memcachedClient.get(key)
    }

    def set(String key, Object value) {
        memcachedClient.set(key, 600, value)
    }

    def delete(String key) {
        memcachedClient.delete(key)
    }

    def clear() {
        memcachedClient.flush()
    }

    def update(key, function) {
        def value = function()
        if (value == null) value = NULL
        set(key, value)
        return value
    }

    def get(key, function) {
        def value = get(key)
        if (value == null) {
            value = update(key, function)
        }
        return (value == NULL) ? null : value;
    }
}

Note: Choose host according to your host name. There is a cache timeout in set() method (600 which is 15 minutes), you can change that according to your requirement.

MemcachedService meets ContactController

To add the newly created MemcachedService into your ContactController, add the following line to your ContactController:

class ContactController {

    def memcachedService

    ...

}

you can call set() method of memcached service like

memcachedService.set(key,value)

you can call get() method of memcached service like

def cachedContactInstanceList = memcachedService.get("key")
log.debug "output: "+cachedContactInstanceList
if(cachedContactInstanceList == null){
// no key is found with the given key name, 
//so you have to call set() method here to set the key.
}
else{
// you got the list, you can perform any offset like action on this too.
}

To flush all cached data:

	
telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
flush_all
OK

>Hope it helps !

Varun Sharma varun.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Creating a simple recommendation engine using Apache Mahout in Grails app

November 27, 2012 by arun kumar

I have integrated mahout in one of my projects in grails so I wanted to share some thoughts on how we can create recommendation engine using Apache Mahout.

First of all What is Apache Mahout ?

The Apache Mahout is an open source machine learning library from Apache. It's goal is to build scalable machine learning libraries. The Algorithms Mahout implements fall under of machine learning or collective intelligence. Mahout has Collaborative Filtering, User and Item based recommender

In This blog i am sharing thoughts about Mahout recommendations and various recommendation Algorithm.

What is recommendation engine ?

Recommender engines are the most recognizable machine learning technique used today. you have seen various services or sites that attempt to recommend Books or Movies based on your past actions. They try to infer tastes and preferences and identify unknown items that are of interest.

Mahout provides various Algorithms to give better item recommendation to various user according to their taste.

  • 1. User-based recommender
  • 2. Item-based recommender
  • 3. Slope-one recommander

The brief description about these algorithms are as follows-

User-based recommender algorithm-

The user-based recommender algorithm comes out of this intuition .It's a process of recommending items to some user, denoted by u, as seen below:

for every item i that u has no preference for yet
    for every other user v that has a preference for i
    compute a similarity s between u and v
      incorporate v's preference for i, weighted by s, into a running average
return the top items, ranked by weighted average.

it would be terribly slow to examine every item. In reality a neighborhood of most similar users to computed first, and only items known to those users are considered:

for every other user w
   compute a similarity s between u and w
  retain the top users , ranked by similarity , as a neighborhood n
     for every item i that some user in n has a preference for i
   compute a similarity s between u and v
     incorporate v's preference for i ,weighed by s, into a running average.

The primary difference is that similar users are found first ,before seeing what those most-similar users are interested in.Those items becomes the candidates for recommendation. the rest are same.

This is the standard user-based recommender algorithm and the way it's implemented in Mahout.

Item-based recommender algorithm-

Item-based recommendation is derived from how similar items are to items . instead of users to users.In Mahout this means they are based on an ItemSimilarity implemeention instead of UserSimilarity

for every item i that u has no preference for yet
   for every item j that u has a preference for
  compute a similarity s between i and j
  add u's preference for j , weighted by s, to a running average
  return the top items ,ranked by weighted average.

The third line in above algorithms shows how it's based on item-item similarities,not user-user similarities as before.

Slope-one recommender algorithm-

The Slope-one name comes from the fact that the recommender algorithm starts with the assumption that there's some linear relationship between preference values for one item and another,that it's valid to estimate the preferences for some item Y based on the preferences for item X ,via some linear function like Y=mX+b. Then the slope-one recommender makes the additional simplifying assumption that m=1 : slope one .It just remains to find b=Y-X, the (average) difference in preference value , for every pair of items.

This means the algorithm consists of a significant preprocessing phase, in which all item-item preference value differences are computed:

for every item i
  for every other item j
    for every user u expressing preference for both i and j
  add the difference in u's preference for i and j to an average.

And then ,the recommendation algorithm looks like this:

for every item i the user u expresses no preference for
   for every item j that user u expresses a preference for
  find the average preference difference between j and i
     add this diff to u's preference value for j
     add this to a running average
  return the top items ranked by these averages.

Its performance does not depend upon the number of users in the data model. So Slope one is attractive and fast like an Item-based recommender.

Now i am using Mahout-recommender plugin in grails to create a recommender.

Hope you have integrated mahout in grails if not please follow steps from Mahout Integration with Grails

After integrating mahout recommender plugin in grails app and configure data model with mysql using

     mahout.recommender.data.model='mysql'
	

in config.groovy

Then create a TastePreferences domain class in your mysql database with userId , itemId and preference field something like that

package mahoutrecommander
import org.apache.commons.lang.builder.HashCodeBuilder

class TastePreferences implements Serializable {
  long userId
  long itemId
  float preference
  static constraints = {
  	userId()
  	itemId()
 	preference range: 0.0f..5.0f
  }

  boolean equals(other) {
      if(!(other instanceof TastePreferences)) {
         return false
      }
      log.debug "other"
  	other.userId == userId && other.itemId == itemId
  }

  int hashCode() {
      def builder = new HashCodeBuilder()
      builder.append userId
      builder.append itemId
      builder.toHashCode()
  }

  static mapping = {
     id composite: ['userId', 'itemId']
     version false
  }
}
    

Bydefault plugin uses TastePreferences named domain class if you want to use any other table for mahout recommender you can configure it in config.groovy

mahout.recommender.preference.table='tableName'
mahout.recommender.preference.userIdColumn='userIdColumn'
mahout.recommender.preference.itemIdColumn='itemIdColumn'
mahout.recommender.preference.valueColumn='preference value'
    

you can use mahout-recommender plugin via three mode

  • 1 input
  • 2 config
  • 3 class
mahout.recommender.mode = 'input'  // 'input', 'config' or 'class' in config.groovy
	

if mode is 'input' then user can pass parameters to recommender controller something as follows-

params.userID-user id of that user whom we are providing recommendation

params.howMany- how many recommendation we want to show to the user otherwise it takes default value.

params.hasPreference-it is boolean value it can be true or false.

params.r- recommender selected like user-based recommender ,item-based recommender or slope-one recommender.

params.s- similarity that can be pearson correlation, Euclidian distance ,Log-likelihood ,Tanimoto coefficient these are different approach to find out similarity.

params.n-it contains neighborhood.

params.w- it is a boolean value that give withWeighting or not.

You can provide these values from config.groovy also as follows:

mahout.recommender.mode="config" //in config of project. give these values in config.groovy.
mahout.recommender.selected=' '
mahout.recommender.hasPreference=' '
mahout.recommender.similarity=' '
mahout.recommender.withWeighting=' '
mahout.recommender.neighborhood=' '
    

and just pass userId and howMany in parameters to recommender controller all other recommender configuration it will pick from config file.

And now last is class mode ,it is used to create custom recommender if you want to use this part then change

mahout.recommander.mode="class"

and also give name of that class in which you are building recommender.

mahout.recommender.builderClass='className'
    

You can use test data in TastePreferences table as follows to check recommender engine working.

+---------+---------+------------+
| user_id | item_id | preference |
+---------+---------+------------+
|       1 |     101 |          5 |
|       1 |     102 |          3 |
|       1 |     103 |          2 |
|       2 |     101 |          2 |
|       2 |     102 |        2.5 |
|       2 |     103 |          5 |
|       2 |     104 |          2 |
|       3 |     101 |        2.5 |
|       3 |     104 |          4 |
|       3 |     105 |        4.5 |
|       3 |     107 |          5 |
|       4 |     101 |          5 |
|       4 |     103 |          3 |
|       4 |     104 |        4.5 |
|       4 |     106 |          4 |
|       5 |     101 |          4 |
|       5 |     102 |          3 |
|       5 |     103 |          2 |
|       5 |     104 |          4 |
|       5 |     105 |        3.5 |
|       5 |     106 |          0 |
+---------+---------+------------+

Suppose our recommender mode is input in config when we start our project in grails it will show recommender controller in home page select that it will show an input form in which you can pass parameters as discussed above and click on submit button.

Suppose we are using userId 1 in input field and want to give recommendation to user 1 then it will show result

 

Now you are getting recommendation. Well that working fine.

hope it helps ! to create recommendation in grails app.

Arun kumar

Resource plugin for performance optimization of Grails app

October 12, 2012 by Nagesh Chauhan

In my recent projects, I have noticed that the amount of time it takes for a Web Page to load is just one of the common complaints from web users.  Among a number of causes behind this problem the big one is page size that increases download time.  A good rule of optimization is to keep only what is necessary and keeping css and script size as small as possible.There are many ways to make your web application appear fast by tuning application components.

Grails provides a number of plugins to improve web application performance, some of frequently used plugins are : UI Performance Plugin, Google Website Optimizer, Canonical Tagging Plugin for SEO, Compress Plugin and much more .

The main idea behind performance and optimization is how smartly we utilize our resources , to make it more easy Grails provides a very useful plugin named "Resources" .This plugin provides a very effective way of adding static contents to your web page and gives a clean image to bundle all your css and js files in a single file. Infact you dont even need to combine your css/Js physically, "Resources" w'll do all these stuff for you dynamically.

These days i am working on a project and my overall goal is to make the application more optimize and fast to appear over browser. "Resources" plugin helped me out in an intelligent way . Today i am going to share my experience and knowledge that w'll help you to implement the plugin in your apps.

Step 1 : First of all we need to install "Resources"  plugin to feel the real magic.

Step 2:  After installing the plugin our next target is to bundle all those css and JS together as a module .

To do this we can create a file in grails-app/conf/ with a name that ends in “Resources.groovy“ or we can add these modules in resources.groovy ,to make it simple lets create AppResources.groovy and use the DSL to declare the resource :

modules = {
	index { 
        resource url:'site-css/reset.css'
		resource url:'site-css/style.css'
		
		resource url:'site-js/jquery.coda-slider-2.0.js'
		resource url:'site-js/jquery.simplyScroll.js'
               }
	}

Step 3 :  Our last step is to add those modules in appropriate gsp's , by doing this we w'll be able to send all those js/css bundles as a single file .

'Resources' provides a rich tag support to add 'css/Js'  efficiently  to gsp's, but here we w'll discuss two very useful tags only and that’s enough for now.

The r:require tag tells the framework which resource module the current GSP requires. The framework will make sure that all the resources declared in those modules are pulled in  the correct order, and other one is  r:layoutResources tag that we need to add on two places , because one will render the resources that we need to link to in the <head> section of our page (all your CSS, and some of our JavaScript, maybe some favico or iPhone icons). The other goes at the end of the <body> of our page, to render any “deferred” resources, which is usually just your JavaScript code.














and we are done with it , by doing this we w'll be able to bundle all our js/css in a single file before sending them over the network .

To make sure if we did it correctly just check it in 'page source' ,to open page source right click on page and select 'View Page Source'

after implementing the ‘css/js’ merge successfully all your indivisual js/css links w’ll be raplaced by two lines like



disposition

The disposition keyword that we used after resource tells the framework that which part of the page, the resource belongs to .The default dispositions supported are “head” and “defer” but in fact resources can define any disposition they like .The framework applies a default disposition based on the type of the resource ,so CSS always defaults to “head” but JavaScript always defaults to “defer”, so that it runs only when the rest of the page has loaded.

Resource modules usually contain multiple resources and the main reason to specify a disposition when declaring a resource is to force JavaScript to load in the <head> section of the page. To achieve that you just update your resource declaration to include a “disposition” attribute:

modules = {
 index {
	resource url:'site-css/reset.css'
	resource url:'site-css/style.css'
	resource url:'site-css/js-scroll.css'
	resource url:'site-js/jquery.min.js',disposition:'head'
	      }
		  }

Points to remember

1 -  Most of the js files are very much dependent on order , so while adding js files to module we must take care of their order .

2 - In case we are having some js file in our module on which other files are dependent, than we should place layoutResources tag as the very first element in head .














3 - If we are trying to add more than 1 module to a page , than both modules try to render on single layoutResources tag , and this may lead to an error , so its better to have a single module per page.

 

 

Hope it helps !

Nagesh Chauhan

www.oodlestechnologies.com

Using facets in Solr using Solr4J in Java or Grails applications

October 08, 2012 by Jasgeet Singh

I am using faceting, one of the features of Solr (java search server) in my current project  and would like to share my experience and learning.

Faceting is Solr's killer-feature. It's a must-have feature for most search implementations, especially those with structured data. Faceting enhances search results with aggregated information over all the documents found in the search, not the entire index.Faceted search is also called faceted browsing, faceted navigation, guided navigation and sometimes parametric search.Now might be a good time for a screenshot,

facet

If we revisit the comparison of search technology to databases, then faceting is more or less analogous to SQL's GROUP BY feature on a column with count(*). However, in Solr, facet processing is performed subsequent to an existing search as part of a single request-response with both the primary search results and the faceting results coming back together. Like as in following screenshot after selecting some facet values we have breadcrumb trail using the following snippet:

def solrQuery = new SolrQuery( “*” )
solrQuery.setFilterQueries (/subcat: Accommodation Provider AND tags: tours/)

Note: *- query parameter which matches all documents

fq - (filter query) parameter, which allows one to filter by a query.

facet

Faceting Field Values

Field value faceting is the most common type of faceting. The following are the request parameters for using it.

• facet.field: You must set this parameter to a field's name in order to facet on that field. Repeat this parameter for each field to be faceted on.

solrQuery.addFacetField(“subcat”)
solrQuery.addFacetField(“tags”)
solrQuery.addFacetField(“languages”)

Note: parameter – field name from the IndexSchema.

• facet.sort : It is set to either count to sort the facet values by descending totals or to index to sort lexicographically, as if you sorted on the field. If facet.limitis greater than zero (it's 100 by default), then Solr picks count as the default, otherwise index is chosen.

solrQuery.setFacetSort(FacetParams.FACET_SORT_INDEX)
solrQuery.setFacetSort(FacetParams.FACET_SORT_COUNT)

•facet.limit: It defaults to 100. It limits the number of facet values returned in the searchresults of a field. As these are usually going to be displayed to the user, it doesn't make sense to have a large number of these in the response. If you need all of them then disable the limit with a value of -1.

solrQuery.setFacetLimit(10)

• facet.mincount: This defaults to 0. It filters out facet values that have facet counts less than this. This is applied before limit and offset so that paging works as expected. It is common to set this to 1 since 0 is almost useless.

solrQuery.setFacetMinCount(1)

• facet.missing: It defaults to blank and is set to true or on for the facet value listing to include an unnamed count at the end, which is the number of searched documents that have no indexed terms.

solrQuery.setFacetMissing(FacetParams.FACET_MISSING)

Resources

Read more about Solr on the Solr Home Page.

Read Solr’s Documentation

Read the Solr tutorial

Powered byApache Solr

Follow Us

Recent Entries