mahout-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sro...@apache.org
Subject svn commit: r793519 - in /lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl: common/jdbc/ model/jdbc/ recommender/slopeone/jdbc/ similarity/jdbc/
Date Mon, 13 Jul 2009 09:44:45 GMT
Author: srowen
Date: Mon Jul 13 09:44:44 2009
New Revision: 793519

URL: http://svn.apache.org/viewvc?rev=793519&view=rev
Log:
Initial cut at MySQLJDBCItemSimilarity

Added:
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java
Modified:
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java

Added: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java?rev=793519&view=auto
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
(added)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
Mon Jul 13 09:44:44 2009
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.common.jdbc;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.mahout.cf.taste.common.TasteException;
+
+import javax.sql.DataSource;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * A helper class with common elements for several JDBC-related components.
+ */
+public abstract class AbstractJDBCComponent {
+
+  private static final Logger log = LoggerFactory.getLogger(AbstractJDBCComponent.class);
+
+  public static final String DEFAULT_DATASOURCE_NAME = "jdbc/taste";
+  private static final int DEFAULT_FETCH_SIZE = 1000; // A max, "big" number of rows to buffer
at once
+
+  protected static void checkNotNullAndLog(String argName, Object value) {
+    if (value == null || value.toString().length() == 0) {
+      throw new IllegalArgumentException(argName + " is null or empty");
+    }
+    log.debug("{}: {}", argName, value);
+  }
+
+  protected static void checkNotNullAndLog(String argName, Object[] values) {
+    if (values == null || values.length == 0) {
+      throw new IllegalArgumentException(argName + " is null or zero-length");
+    }
+    for (Object value : values) {
+      checkNotNullAndLog(argName, value);
+    }
+  }
+
+
+  /**
+   * <p>Looks up a {@link DataSource} by name from JNDI. "java:comp/env/" is prepended
to the argument before looking up
+   * the name in JNDI.</p>
+   *
+   * @param dataSourceName JNDI name where a {@link DataSource} is bound (e.g. "jdbc/taste")
+   * @return {@link DataSource} under that JNDI name
+   * @throws TasteException if a JNDI error occurs
+   */
+  public static DataSource lookupDataSource(String dataSourceName) throws TasteException
{
+    Context context = null;
+    try {
+      context = new InitialContext();
+      return (DataSource) context.lookup("java:comp/env/" + dataSourceName);
+    } catch (NamingException ne) {
+      throw new TasteException(ne);
+    } finally {
+      if (context != null) {
+        try {
+          context.close();
+        } catch (NamingException ne) {
+          log.warn("Error while closing Context; continuing...", ne);
+        }
+      }
+    }
+  }
+
+  protected int getFetchSize() {
+    return DEFAULT_FETCH_SIZE;
+  }
+
+  protected void advanceResultSet(ResultSet resultSet, int n) throws SQLException {
+    resultSet.relative(n);
+  }
+
+}

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java?rev=793519&r1=793518&r2=793519&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
(original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
Mon Jul 13 09:44:44 2009
@@ -25,6 +25,7 @@
 import org.apache.mahout.cf.taste.impl.common.IteratorIterable;
 import org.apache.mahout.cf.taste.impl.common.Retriever;
 import org.apache.mahout.cf.taste.impl.common.SkippingIterator;
+import org.apache.mahout.cf.taste.impl.common.jdbc.AbstractJDBCComponent;
 import org.apache.mahout.cf.taste.impl.model.GenericItem;
 import org.apache.mahout.cf.taste.impl.model.GenericPreference;
 import org.apache.mahout.cf.taste.impl.model.GenericUser;
@@ -70,18 +71,15 @@
  * code, you will run into subtle problems because the {@link Long} values won't be equal
to or compare correctly to the
  * underlying {@link String} key values.</p>
  */
-public abstract class AbstractJDBCDataModel implements JDBCDataModel {
+public abstract class AbstractJDBCDataModel extends AbstractJDBCComponent implements JDBCDataModel
{
 
   static final Logger log = LoggerFactory.getLogger(AbstractJDBCDataModel.class);
 
-  public static final String DEFAULT_DATASOURCE_NAME = "jdbc/taste";
   public static final String DEFAULT_PREFERENCE_TABLE = "taste_preferences";
   public static final String DEFAULT_USER_ID_COLUMN = "user_id";
   public static final String DEFAULT_ITEM_ID_COLUMN = "item_id";
   public static final String DEFAULT_PREFERENCE_COLUMN = "preference";
 
-  static final int DEFAULT_FETCH_SIZE = 1000; // A max, "big" number of rows to buffer at
once
-
   private final DataSource dataSource;
   private final String preferenceTable;
   private final String userIDColumn;
@@ -198,39 +196,6 @@
 
   }
 
-  private static void checkNotNullAndLog(String argName, Object value) {
-    if (value == null || value.toString().length() == 0) {
-      throw new IllegalArgumentException(argName + " is null or empty");
-    }
-    log.debug("{}: {}", argName, value);
-  }
-
-  /**
-   * <p>Looks up a {@link DataSource} by name from JNDI. "java:comp/env/" is prepended
to the argument before looking up
-   * the name in JNDI.</p>
-   *
-   * @param dataSourceName JNDI name where a {@link DataSource} is bound (e.g. "jdbc/taste")
-   * @return {@link DataSource} under that JNDI name
-   * @throws TasteException if a JNDI error occurs
-   */
-  public static DataSource lookupDataSource(String dataSourceName) throws TasteException
{
-    Context context = null;
-    try {
-      context = new InitialContext();
-      return (DataSource) context.lookup("java:comp/env/" + dataSourceName);
-    } catch (NamingException ne) {
-      throw new TasteException(ne);
-    } finally {
-      if (context != null) {
-        try {
-          context.close();
-        } catch (NamingException ne) {
-          log.warn("Error while closing Context; continuing...", ne);
-        }
-      }
-    }
-  }
-
   /** @return the {@link DataSource} that this instance is using */
   @Override
   public DataSource getDataSource() {
@@ -253,14 +218,6 @@
     return preferenceColumn;
   }
 
-  protected int getFetchSize() {
-    return DEFAULT_FETCH_SIZE;
-  }
-
-  protected void advanceResultSet(ResultSet resultSet, int n) throws SQLException {
-    resultSet.relative(n);
-  }
-
   @Override
   public Iterable<? extends User> getUsers() throws TasteException {
     log.debug("Retrieving all users...");

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java?rev=793519&r1=793518&r2=793519&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java
(original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java
Mon Jul 13 09:44:44 2009
@@ -29,12 +29,15 @@
  * default, this class assumes that there is a {@link DataSource} available under the JNDI
name "jdbc/taste", which
  * gives access to a database with a "taste_preferences" table with the following schema:</p>
  *
- * <table> <tr><th>user_id</th><th>item_id</th><th>preference</th></tr>
<tr><td>ABC</td><td>123</td><td>0.9</td></tr>
- * <tr><td>ABC</td><td>456</td><td>0.1</td></tr>
<tr><td>DEF</td><td>123</td><td>0.2</td></tr>
- * <tr><td>DEF</td><td>789</td><td>0.3</td></tr>
</table>
+ * <table>
+ * <tr><th>user_id</th><th>item_id</th><th>preference</th></tr>
+ * <tr><td>ABC</td><td>123</td><td>0.9</td></tr>
+ * <tr><td>ABC</td><td>456</td><td>0.1</td></tr>
+ * <tr><td>DEF</td><td>123</td><td>0.2</td></tr>
+ * <tr><td>DEF</td><td>789</td><td>0.3</td></tr>
+ * </table>
  *
- * <p><code>user_id</code> must have a type compatible with the Java <code>String</code>
type. <code>item_id</code> must
- * have a type compatible with the Java <code>String</code> type. <code>preference</code>
must have a type compatible
+ * <p><code>preference</code> must have a type compatible
  * with the Java <code>double</code> type. For example, the following command
sets up a suitable table in MySQL,
  * complete with primary key and indexes:</p>
  *

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java?rev=793519&r1=793518&r2=793519&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java
(original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java
Mon Jul 13 09:44:44 2009
@@ -23,6 +23,7 @@
 import org.apache.mahout.cf.taste.impl.common.IOUtils;
 import org.apache.mahout.cf.taste.impl.common.RefreshHelper;
 import org.apache.mahout.cf.taste.impl.common.RunningAverage;
+import org.apache.mahout.cf.taste.impl.common.jdbc.AbstractJDBCComponent;
 import org.apache.mahout.cf.taste.model.Item;
 import org.apache.mahout.cf.taste.model.JDBCDataModel;
 import org.apache.mahout.cf.taste.model.Preference;
@@ -46,12 +47,10 @@
  * org.apache.mahout.cf.taste.model.DataModel} used; it needs a {@link JDBCDataModel} attached
to the same database
  * since its efficent operation depends on accessing preference data in the database directly.</p>
  */
-public abstract class AbstractJDBCDiffStorage implements DiffStorage {
+public abstract class AbstractJDBCDiffStorage extends AbstractJDBCComponent implements DiffStorage
{
 
   private static final Logger log = LoggerFactory.getLogger(AbstractJDBCDiffStorage.class);
 
-  static final int DEFAULT_FETCH_SIZE = 1000; // A max, "big" number of rows to buffer at
once
-  
   public static final String DEFAULT_DIFF_TABLE = "taste_slopeone_diffs";
   public static final String DEFAULT_ITEM_A_COLUMN = "item_id_a";
   public static final String DEFAULT_ITEM_B_COLUMN = "item_id_b";
@@ -83,9 +82,18 @@
                                     String createDiffsSQL,
                                     String diffsExistSQL,
                                     int minDiffCount) throws TasteException {
-    if (dataModel == null) {
-      throw new IllegalArgumentException("dataModel is null");
-    }
+
+    checkNotNullAndLog("dataModel", dataModel);
+    checkNotNullAndLog("getDiffSQL", getDiffSQL);
+    checkNotNullAndLog("getDiffsSQL", getDiffsSQL);
+    checkNotNullAndLog("getAverageItemPrefSQL", getAverageItemPrefSQL);
+    checkNotNullAndLog("updateDiffSQLs", updateDiffSQLs);
+    checkNotNullAndLog("removeDiffSQLs", removeDiffSQLs);
+    checkNotNullAndLog("getRecommendableItemsSQL", getRecommendableItemsSQL);
+    checkNotNullAndLog("deleteDiffsSQL", deleteDiffsSQL);
+    checkNotNullAndLog("createDiffsSQL", createDiffsSQL);
+    checkNotNullAndLog("diffsExistSQL", diffsExistSQL);
+
     if (minDiffCount < 0) {
       throw new IllegalArgumentException("minDiffCount is not positive");
     }
@@ -117,10 +125,6 @@
     }
   }
 
-  protected int getFetchSize() {
-    return DEFAULT_FETCH_SIZE;
-  }
-
   @Override
   public RunningAverage getDiff(Object itemID1, Object itemID2) throws TasteException {
     Connection conn = null;

Added: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java?rev=793519&view=auto
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java
(added)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java
Mon Jul 13 09:44:44 2009
@@ -0,0 +1,149 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.similarity.jdbc;
+
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
+import org.apache.mahout.cf.taste.model.Item;
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.common.Refreshable;
+import org.apache.mahout.cf.taste.common.NoSuchItemException;
+import org.apache.mahout.cf.taste.impl.common.IOUtils;
+import org.apache.mahout.cf.taste.impl.common.jdbc.AbstractJDBCComponent;
+import org.apache.mahout.cf.taste.impl.model.jdbc.ConnectionPoolDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+import java.util.Collection;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * An {@link ItemSimilarity} which draws pre-computed item-item similarities from
+ * a database table via JDBC.
+ */
+public abstract class AbstractJDBCItemSimilarity extends AbstractJDBCComponent implements
ItemSimilarity {
+
+  private static final Logger log = LoggerFactory.getLogger(AbstractJDBCItemSimilarity.class);
+
+  static final String DEFAULT_SIMILARITY_TABLE = "taste_item_similarity";
+  static final String DEFAULT_ITEM_A_ID_COLUMN = "item_id_a";
+  static final String DEFAULT_ITEM_B_ID_COLUMN = "item_id_b";
+  static final String DEFAULT_SIMILARITY_COLUMN = "similarity";
+
+  private final DataSource dataSource;
+  private final String similarityTable;
+  private final String itemAIDColumn;
+  private final String itemBIDColumn;
+  private final String similarityColumn;
+  private final String getItemItemSimilaritySQL;
+
+  protected AbstractJDBCItemSimilarity(DataSource dataSource,
+                                       String getItemItemSimilaritySQL) {
+    this(dataSource,
+         DEFAULT_SIMILARITY_TABLE,
+         DEFAULT_ITEM_A_ID_COLUMN,
+         DEFAULT_ITEM_B_ID_COLUMN,
+         DEFAULT_SIMILARITY_COLUMN,
+         getItemItemSimilaritySQL);
+  }
+
+  protected AbstractJDBCItemSimilarity(DataSource dataSource,
+                                       String similarityTable,
+                                       String itemAIDColumn,
+                                       String itemBIDColumn,
+                                       String similarityColumn,
+                                       String getItemItemSimilaritySQL) {
+
+    log.debug("Creating AbstractJDBCItemSimilarity...");
+
+    checkNotNullAndLog("similarityTable", similarityTable);
+    checkNotNullAndLog("itemAIDColumn", itemAIDColumn);
+    checkNotNullAndLog("itemBIDColumn", itemBIDColumn);
+    checkNotNullAndLog("similarityColumn", similarityColumn);
+
+    checkNotNullAndLog("getItemItemSimilaritySQL", getItemItemSimilaritySQL);
+
+    if (!(dataSource instanceof ConnectionPoolDataSource)) {
+      log.warn("You are not using ConnectionPoolDataSource. Make sure your DataSource pools
connections " +
+          "to the database itself, or database performance will be severely reduced.");
+    }
+
+    this.dataSource = dataSource;
+    this.similarityTable = similarityTable;
+    this.itemAIDColumn = itemAIDColumn;
+    this.itemBIDColumn = itemBIDColumn;
+    this.similarityColumn = similarityColumn;
+    this.getItemItemSimilaritySQL = getItemItemSimilaritySQL;
+  }
+
+  protected String getSimilarityTable() {
+    return similarityTable;
+  }
+
+  protected String getItemAIDColumn() {
+    return itemAIDColumn;
+  }
+
+  protected String getItemBIDColumn() {
+    return itemBIDColumn;
+  }
+
+  protected String getSimilarityColumn() {
+    return similarityColumn;
+  }
+
+  @Override
+  public double itemSimilarity(Item item1, Item item2) throws TasteException {
+    Connection conn = null;
+    PreparedStatement stmt = null;
+    ResultSet rs = null;
+
+    try {
+      conn = dataSource.getConnection();
+      stmt = conn.prepareStatement(getItemItemSimilaritySQL, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
+      stmt.setFetchDirection(ResultSet.FETCH_FORWARD);
+      stmt.setFetchSize(getFetchSize());
+      stmt.setObject(1, item1.getID());
+      stmt.setObject(2, item2.getID());
+
+      log.debug("Executing SQL query: {}", getItemItemSimilaritySQL);
+      rs = stmt.executeQuery();
+
+      if (rs.next()) {
+        return rs.getDouble(1);
+      } else {
+        throw new NoSuchItemException();
+      }
+
+    } catch (SQLException sqle) {
+      log.warn("Exception while retrieving user", sqle);
+      throw new TasteException(sqle);
+    } finally {
+      IOUtils.quietClose(rs, stmt, conn);
+    }
+  }
+
+  @Override
+  public void refresh(Collection<Refreshable> alreadyRefreshed) {
+    // do nothing
+  }
+
+}

Added: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java?rev=793519&view=auto
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java
(added)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java
Mon Jul 13 09:44:44 2009
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.similarity.jdbc;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
+
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * <p>An {@link ItemSimilarity} backed by a MySQL database and accessed via JDBC.
+ * It may work with other JDBC databases. By default, this class assumes that there is a
{@link DataSource}
+ * available under the JNDI name "jdbc/taste", which
+ * gives access to a database with a "taste_item_similarity" table with the following schema:</p>
+ *
+ * <table>
+ * <tr><th>item_id_a</th><th>item_id_b</th><th>similarity</th></tr>
+ * <tr><td>ABC</td><td>DEF</td><td>0.9</td></tr>
+ * <tr><td>DEF</td><td>EFG</td><td>0.1</td></tr>
+ * </table>
+ *
+ * <p>For example, the following command sets up a suitable table in MySQL,
+ * complete with primary key and indexes:</p>
+ *
+ * <pre>
+ * CREATE TABLE taste_item_similarity (
+ *   item_id_a VARCHAR(10) NOT NULL,
+ *   item_id_b VARCHAR(10) NOT NULL,
+ *   similarity FLOAT NOT NULL,
+ *   PRIMARY KEY (item_id_a, item_id_b),
+ * )
+ * </pre>
+ *
+ *
+ * @see org.apache.mahout.cf.taste.impl.recommender.slopeone.jdbc.MySQLJDBCDiffStorage
+ * @see org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel
+ */
+public final class MySQLJDBCItemSimilarity extends AbstractJDBCItemSimilarity {
+
+  public MySQLJDBCItemSimilarity() throws TasteException {
+    this(DEFAULT_DATASOURCE_NAME);
+  }
+
+  public MySQLJDBCItemSimilarity(String dataSourceName) throws TasteException {
+    this(lookupDataSource(dataSourceName));
+  }
+
+  public MySQLJDBCItemSimilarity(DataSource dataSource) {
+    this(dataSource,
+         DEFAULT_SIMILARITY_TABLE,
+         DEFAULT_ITEM_A_ID_COLUMN,
+         DEFAULT_ITEM_B_ID_COLUMN,
+         DEFAULT_SIMILARITY_COLUMN);
+  }
+
+  public MySQLJDBCItemSimilarity(DataSource dataSource,
+                                 String similarityTable,
+                                 String itemAIDColumn,
+                                 String itemBIDColumn,
+                                 String similarityColumn) {
+    super(dataSource,
+          similarityTable,
+          itemAIDColumn,
+          itemBIDColumn,
+          similarityColumn,
+          "SELECT " + similarityColumn + " FROM " + similarityTable + " WHERE " + itemAIDColumn
+ "=? AND " +
+          itemBIDColumn + "=?");
+  }
+
+  @Override
+  protected int getFetchSize() {
+    // Need to return this for MySQL Connector/J to make it use streaming mode
+    return Integer.MIN_VALUE;
+  }
+
+}
\ No newline at end of file



Mime
View raw message