2013-04-14 2 views
2

a6347324, b7432408, f54789922 (숫자가 아닌) 및 숫자 항목 ID와 같은 사용자 ID가 있습니다. Myrrix에서 REST API를 사용하여 이러한 사용자 - 항목 쌍을 삽입 할 수 있기를 원합니다. 그러나 /pref/a6347324/1234은 오류를 반환합니다. 라인 012에있는 parseLong을 고려하면, https://github.com/myrrix/myrrix-recommender/blob/master/web-common/src/net/myrrix/web/servlets/PreferenceServlet.javaMyrrix 서빙 레이어에서 REST API를 통해 문자열 사용자 ID를 삽입하는 방법

버전 0.11을 사용하고 있습니다. 동등한 숫자 ID와 같은 문자열 태그를 반환하지 않기 때문에 "태그"기능을 사용하고 싶지 않으며 태그가 반환되지 않으므로 because API에서 작동하지 않을 것이라고 생각합니다. 이 문제가 곧 수정 될 예정입니까? 즉각적으로 사용하거나 구현할 수있는 즉각적인 해결 방법이 있습니까?

+0

찾은 해결책을 게시 할 수 있습니까? :) – ksiomelo

+1

@ksiomelo 방금 추가 한 답변을 확인하십시오. 희망이 도움이됩니다. – Nilesh

+0

감사합니다 Nilesh, 대단히 감사하겠습니다. – ksiomelo

답변

2

REST API 자체는 설계 상 숫자 ID로 작동합니다. 숫자 ID를 만들기 위해 다른 ID (숫자 또는하지 않음)를 잠재적으로 해싱하는 것은 클라이언트입니다. 대신 TranslatingClientRecommender을 사용하면 번역을 원래 ID로 되돌릴 수 있습니다.

추가 혜택은 잠재적으로 약간의 보안입니다. 실제 사용자 및 항목 ID를 실제로 서비스에 전송할 필요가 없습니다. Amazon EC2와 같은 타사 클라우드에서 호스팅되는 경우 중요 할 수 있습니다.

+0

클라이언트와 서버가 모두 같은 시스템에 있다고 가정합니다. 내 응용 프로그램은 PHP로되어 있으므로 REST-API를 사용하는 것은 쉽습니다. 그러나 TranslatingClientRecommender를 사용하면 java myrrix-client를 사용해야 할 것입니다. 그렇습니까? 그것이 언제나 JVM을 가동시켜야한다는 것을 고려할 때, 모든 기본 설정 추가 나 실시간 작업을 위해 호출해서는 안됩니다. 내 유일한 옵션은 기존 REST-API 주위에 사용자 정의 래퍼를 작성하는 것입니다. 그렇지 않습니까? – Nilesh

+0

예. 그렇게하지 않겠습니다. Michael Salib은 비공식 PHP 클라이언트 인 https://github.com/michelsalib/bcc-myrrix를 만들었지 만 해싱은하지 않는다고 생각합니다. PHP에서 원하는대로 해시를 수행 할 수 있습니다. 유일한 어려움은 어떻게 든 역 매핑을 유지하는 것입니다.그런 다음 필요에 따라 번역합니다. Java와 일관성을 유지하려면 스트림의 MD5 해시 중 하위 64 비트를 사용하십시오. –

+0

예, 이미 bcc-myrrix를 사용하고 있지만 변환/해싱은 수행하지 않습니다. 필자가 언급 한 MD5 해시를 사용하고 아마 MySQL 5.6 InnoDB/memcached 키 - 값 저장소를 사용하여지도를 저장할 것입니다. 감사. – Nilesh

1

실제로이 문제를 해결하는 방법에 대한 세부 정보를 추가하기로 결정했습니다. 중요한 수정을 한 후 나중에 객체 지향적으로 만들었습니다. 이것은 이해를 쉽게하기위한 간단한 설명 일뿐입니다.

여기에 TranslatingClientRecommender의 작은 래퍼 인 WebClientRecommender 클래스가 있습니다. 여기

package suggester.client.recommender; 

import java.io.File; 
import java.io.Reader; 
import java.net.URI; 
import java.util.Arrays; 
import java.util.List; 
import net.myrrix.client.MyrrixClientConfiguration; 
import net.myrrix.client.translating.TranslatedRecommendedItem; 
import org.apache.mahout.cf.taste.common.TasteException; 

/** 
* 
* @author Nilesh Chakraborty 
*/ 
public class WebClientRecommender extends AbstractClientRecommender { 

    public WebClientRecommender(MyrrixClientConfiguration myrrixClientConfiguration) { 
     super(myrrixClientConfiguration); 
    } 

    @Override 
    public List<TranslatedRecommendedItem> recommend(String idListFile, String recommendTo, String recommendType, int howMany) throws TasteException { 
     clientRecommender.addItemIDs(new File(idListFile)); 
     List<TranslatedRecommendedItem> recommendations = clientRecommender.recommend(recommendTo, howMany, false, new String[]{recommendType}); 
     return recommendations; 
    } 

    @Override 
    public List<TranslatedRecommendedItem> recommendAnonymous(String idListFile, String recommendType, int howMany, String[] list) throws TasteException { 
     clientRecommender.addItemIDs(new File(idListFile)); 
     float[] values = new float[list.length]; 
     Arrays.fill(values, 30); 
     List<TranslatedRecommendedItem> recommendations = clientRecommender.recommendToAnonymous(list, values, howMany, new String[]{recommendType}, "testID"); 
     return recommendations; 
    } 

    public List<TranslatedRecommendedItem> recommendAnonymous(URI idListFile, String recommendType, int howMany, String[] list) throws TasteException { 
     clientRecommender.addItemIDs(new File(idListFile)); 
     float[] values = new float[list.length]; 
     Arrays.fill(values, 30); 
     List<TranslatedRecommendedItem> recommendations = clientRecommender.recommendToAnonymous(list, values, howMany, new String[]{recommendType}, "testID"); 
     return recommendations; 
    } 

    @Override 
    public void ingest(Reader csvReader) throws TasteException { 
     clientRecommender.ingest(csvReader); 
    } 
} 

AbstractClientRecommender입니다 :

package suggester.client.recommender; 

import java.io.IOException; 
import java.io.Reader; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import net.myrrix.client.ClientRecommender; 
import net.myrrix.client.MyrrixClientConfiguration; 
import net.myrrix.client.translating.TranslatedRecommendedItem; 
import net.myrrix.client.translating.TranslatingClientRecommender; 
import org.apache.mahout.cf.taste.common.TasteException; 

/** 
* 
* @author nilesh 
*/ 
abstract class AbstractClientRecommender { 

    protected TranslatingClientRecommender clientRecommender; 

    public AbstractClientRecommender(MyrrixClientConfiguration myrrixClientConfiguration) { 
     try { 
      clientRecommender = new TranslatingClientRecommender(new ClientRecommender(myrrixClientConfiguration)); 
     } catch (IOException ex) { 
      Logger.getLogger(CLIClientRecommender.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public abstract List<TranslatedRecommendedItem> recommend(String idListFile, String recommendTo, String recommendType, int howMany) throws TasteException; 

    public abstract List<TranslatedRecommendedItem> recommendAnonymous(String idListFile, String recommendType, int howMany, String[] list) throws TasteException; 

    public void ingest(String csvFile) throws TasteException { 
    } 

    public void ingest(Reader csvReader) throws TasteException { 
    } 
} 

지금, 나는 사용자 정의 서블릿에 WebClientRecommender 클래스를 사용하고 있습니다. 여기 SuggesterServlet는 다음과 같습니다

package suggester.client.servlets; 

import com.google.common.base.Splitter; 
import suggester.client.recommender.WebClientRecommender; 
import java.io.IOException; 
import java.net.URL; 
import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import net.myrrix.client.MyrrixClientConfiguration; 
import net.myrrix.web.servlets.AbstractMyrrixServlet; 

/** 
* 
* @author nilesh 
*/ 
public abstract class AbstractSuggesterServlet extends AbstractMyrrixServlet { 

    static final Splitter SLASH = Splitter.on('/').omitEmptyStrings(); 
    private WebClientRecommender recommender; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 
     MyrrixClientConfiguration config = new MyrrixClientConfiguration(); 
     config.setHost(request.getServerName()); 
     config.setPort(request.getServerPort()); 
     recommender = new WebClientRecommender(config); 
    } 

    protected final WebClientRecommender getClientRecommender() { 
     return recommender; 
    } 
} 

이제, 우리가 SuggesterServlet로 이동합니다

package suggester.client.servlets; 

import com.google.common.collect.Iterables; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.net.URISyntaxException; 
import java.util.List; 
import javax.naming.NamingException; 
import javax.servlet.ServletException; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import net.myrrix.client.translating.TranslatedRecommendedItem; 
import org.apache.mahout.cf.taste.common.TasteException; 

/** 
* 
* @author nilesh 
*/ 
public class SuggesterServlet extends AbstractSuggesterServlet { 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 
     super.doGet(request, response); 

     String pathInfo = request.getPathInfo(); 
     String[] pathComponents = Iterables.toArray(SLASH.split(pathInfo), String.class); 

     if (pathComponents.length == 0) { 
      response.sendError(HttpServletResponse.SC_BAD_REQUEST); 
      return; 
     } 

     try { 
      List<TranslatedRecommendedItem> recommended = getClientRecommender().recommendAnonymous(getPropFilePath("proplist").toURI(), request.getParameter("type"), getHowMany(request), pathComponents); 
      output(request, response, recommended); 
     } catch (URISyntaxException use) { 
      response.sendError(HttpServletResponse.SC_BAD_REQUEST, use.toString()); 
     } catch (NamingException ne) { 
      response.sendError(HttpServletResponse.SC_BAD_REQUEST, ne.toString()); 
     } catch (TasteException te) { 
      response.sendError(HttpServletResponse.SC_BAD_REQUEST, te.toString()); 
     } 
    } 

    protected final void output(HttpServletRequest request, 
      ServletResponse response, 
      List<TranslatedRecommendedItem> items) throws IOException { 

     PrintWriter writer = response.getWriter(); 
     // Always print JSON 
     writer.write('['); 
     boolean first = true; 
     for (TranslatedRecommendedItem item : items) { 
      if (first) { 
       first = false; 
      } else { 
       writer.write(','); 
      } 
      writer.write("[\""); 
      writer.write(item.getItemID()); 
      writer.write("\","); 
      writer.write(Float.toString(item.getValue())); 
      writer.write(']'); 
     } 
     writer.write(']'); 
    } 
} 

다음은 소품 파일의 읽기 및합니다 (Myrrix REST 서블릿에 연결)를 TranslatingClientRecommender에 문자열 ID를 추가 , 사용자 정의 서블릿 (HAS-A 관계) 내에 TranslatingClientRecommender을 사용합니다. 이는 기본적으로 내가 한 일입니다. 내 사용자 정의 서블릿을 목록에 추가하기 위해 Myrrix의 web.xml을 수정해야했습니다. 모든 것이 Tomcat의 단일 응용 프로그램 내에서 실행될 수 있습니다.