Return-Path:
Delivered-To: apmail-lucene-mahout-commits-archive@minotaur.apache.org
Received: (qmail 86318 invoked from network); 13 Jul 2009 09:45:01 -0000
Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3)
by minotaur.apache.org with SMTP; 13 Jul 2009 09:45:01 -0000
Received: (qmail 2635 invoked by uid 500); 13 Jul 2009 09:45:11 -0000
Delivered-To: apmail-lucene-mahout-commits-archive@lucene.apache.org
Received: (qmail 2590 invoked by uid 500); 13 Jul 2009 09:45:10 -0000
Mailing-List: contact mahout-commits-help@lucene.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: mahout-dev@lucene.apache.org
Delivered-To: mailing list mahout-commits@lucene.apache.org
Received: (qmail 2581 invoked by uid 99); 13 Jul 2009 09:45:10 -0000
Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230)
by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Jul 2009 09:45:10 +0000
X-ASF-Spam-Status: No, hits=-2000.0 required=10.0
tests=ALL_TRUSTED
X-Spam-Check-By: apache.org
Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4)
by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Jul 2009 09:45:06 +0000
Received: by eris.apache.org (Postfix, from userid 65534)
id A19742388878; Mon, 13 Jul 2009 09:44:45 +0000 (UTC)
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
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 -0000
To: mahout-commits@lucene.apache.org
From: srowen@apache.org
X-Mailer: svnmailer-1.0.8
Message-Id: <20090713094445.A19742388878@eris.apache.org>
X-Virus-Checked: Checked by ClamAV on apache.org
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);
+ }
+ }
+
+
+ /**
+ * Looks up a {@link DataSource} by name from JNDI. "java:comp/env/" is prepended to the argument before looking up
+ * the name in JNDI.
+ *
+ * @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.
*/
-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);
- }
-
- /**
- * Looks up a {@link DataSource} by name from JNDI. "java:comp/env/" is prepended to the argument before looking up
- * the name in JNDI.
- *
- * @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:
*
- * user_id | item_id | preference |
ABC | 123 | 0.9 |
- * ABC | 456 | 0.1 |
DEF | 123 | 0.2 |
- * DEF | 789 | 0.3 |
+ *
+ * user_id | item_id | preference |
+ * ABC | 123 | 0.9 |
+ * ABC | 456 | 0.1 |
+ * DEF | 123 | 0.2 |
+ * DEF | 789 | 0.3 |
+ *
*
- * user_id
must have a type compatible with the Java String
type. item_id
must
- * have a type compatible with the Java String
type. preference
must have a type compatible
+ *
preference
must have a type compatible
* with the Java double
type. For example, the following command sets up a suitable table in MySQL,
* complete with primary key and indexes:
*
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.
*/
-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 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;
+
+/**
+ * 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:
+ *
+ *
+ * item_id_a | item_id_b | similarity |
+ * ABC | DEF | 0.9 |
+ * DEF | EFG | 0.1 |
+ *
+ *
+ * For example, the following command sets up a suitable table in MySQL,
+ * complete with primary key and indexes:
+ *
+ *
+ * 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),
+ * )
+ *
+ *
+ *
+ * @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