2013-10-04 3 views
2

Предположим, у меня есть тестовое приложение, представляющее список друзей. Приложение использует коллекцию, где все документы в следующем формате:Solr индексация коллекции MongoDB

_id : ObjectId("someString"), 
name : "George", 
description : "some text", 
age : 35, 
friends : { 
    [ 
     { 
     name: "Peter", 
     age: 30 
     town: { 
        name_town: "Paris", 
        country: "France" 
       } 
     }, 
     { 
     name: "Thomas", 
     age: 25 
     town: { 
        name_town: "Berlin", 
        country: "Germany" 
       } 
     }, ...    // more friends 
    ] 
} 
...       // more documents 

Как я могу описать такую ​​коллекцию в schema.xml? Мне нужно создать фасетные вопросы, например: «Дайте мне страны, где живут друзья Джорджа». Другой вариант использования может быть: «Вернуть все документы (лица), чей друг 30 лет». и т.д.

Моя первоначальная идея заключается в том, чтобы отметить «друзья» атрибут как текстовое поле с помощью этой schema.xml определения:

<fieldType name="text_wslc" class="solr.TextField" positionIncrementGap="100"> 
.... 
<field name="friends" type="text_wslc" indexed="true" stored="true" /> 

и попытаться найти, например. слова «возраст» и «30» в тексте, но это не очень надежное решение.


Пожалуйста, оставьте в стороне не логически хорошо сформированную архитектуру коллекции. Это всего лишь пример аналогичной проблемы, с которой я столкнулся.

Любая помощь или идея будут высоко оценены.

EDIT: Sample 'schema.xml'

<?xml version="1.0" encoding="UTF-8" ?> 
<schema name="text-schema" version="1.5"> 
    <types> 
     <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/> 
     <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0" /> 
     <fieldType name="trInt" class="solr.TrieIntField" precisionStep="0" omitNorms="true" /> 
     <fieldType name="text_p" class="solr.TextField" positionIncrementGap="100"> 
      <analyzer type="index"> 
       <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
       <filter class="solr.TrimFilterFactory"/> 
       <filter class="solr.WordDelimiterFilterFactory"/> 
       <filter class="solr.LowerCaseFilterFactory"/> 
      </analyzer> 
      <analyzer type="query"> 
       <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
       <filter class="solr.TrimFilterFactory"/> 
       <filter class="solr.WordDelimiterFilterFactory"/> 
       <filter class="solr.LowerCaseFilterFactory"/> 
      </analyzer> 
     </fieldType> 
    </types> 

    <fields> 
      <field name="_id" type="string" indexed="true" stored="true" required="true" /> 
      <field name="_version_" type="long" indexed="true" stored="true"/> 
      <field name="_ts" type="long" indexed="true" stored="true"/> 
      <field name="ns" type="string" indexed="true" stored="true"/>    
      <field name="description" type="text_p" indexed="true" stored="true" /> 
      <field name="name" type="text_p" indexed="true" stored="true" /> 
      <field name="age" type="trInt" indexed="true" stored="true" /> 
      <field name="friends" type="text_p" indexed="true" stored="true" />   <!-- Here is the problem - when the type is text_p, all fields are considered as a text; optimal solution would be something like "collection" tag to mark name_town and town as descendant of the field 'friends' but unfortunately, this is not how the solr works--> 

      <field name="town" type="text_p" indexed="true" stored="true"/> 
      <field name="name_town" type="string" indexed="true" stored="true"/>  
      <field name="town" type="string" indexed="true" stored="true"/> 
    </fields> 

    <uniqueKey>_id</uniqueKey> 

+1

Ну, если вы хотите придерживаться вашей идеи схемы, я не вижу решения для вашего требования. Вам понадобится функция соединения, так как вы хотите сделать что-то вроде вложенных объектов. Нет другого надежного способа запросить что-то вроде этого, не запуская апгрейд-ад. – cheffe

ответ

0

Как Solr является документ-ориентированных вам нужно будет выравниваться столько, сколько вы можете вниз. Согласно образцу, который вы дали, я бы создал schema.xml, как показано ниже.

<?xml version="1.0" encoding="UTF-8" ?> 
<schema name="friends" version="1.0"> 

    <fields> 
     <field name="id" 
      type="int" indexed="true" stored="true" multiValued="false" /> 
     <field name="name" 
      type="text" indexed="true" stored="true" multiValued="false" /> 
     <field name="description" 
      type="text" indexed="true" stored="true" multiValued="false" /> 
     <field name="age" 
      type="int" indexed="true" stored="true" multiValued="false" /> 
     <field name="town" 
      type="text" indexed="true" stored="true" multiValued="false" /> 
     <field name="townRaw" 
      type="string" indexed="true" stored="true" multiValued="false" /> 
     <field name="country" 
      type="text" indexed="true" stored="true" multiValued="false" /> 
     <field name="countryRaw" 
      type="string" indexed="true" stored="true" multiValued="false" /> 
     <field name="friends" 
      type="int" indexed="true" stored="true" multiValued="true" /> 
    </fields> 
    <copyField source="country" dest="countryRaw" /> 
    <copyField source="town" dest="townRaw" /> 

    <types> 
     <fieldType name="string" class="solr.StrField" sortMissingLast="true"/> 
     <fieldType name="int" class="solr.TrieIntField" 
      precisionStep="0" positionIncrementGap="0" /> 
     <fieldType name="text" class="solr.TextField" 
      positionIncrementGap="100"> 
      <analyzer> 
       <tokenizer class="solr.StandardTokenizerFactory" /> 
       <filter class="solr.LowerCaseFilterFactory" /> 
      </analyzer> 
     </fieldType> 
    </types> 
</schema> 

Я бы пошел с подходом к моделированию каждого человека для себя. Связь между двумя людьми моделируется с помощью атрибута друзей, что переводится в массив идентификаторов. Поэтому во время индекса вам нужно будет получить идентификаторы всех друзей для человека и поместить их в это поле.

Большинство других полей являются прямыми. Интересны два поля Raw. Поскольку вы сказали, что хотите сделать грань в стране, вам понадобится страна без изменений или оптимизация для огранки. Обычно типы полей различаются в зависимости от их предназначения (их поиск, огранение ими, автоматическое отключение их и т. Д.). В этом случае страны и города индексируются так же, как они приведены в.

Теперь для случаев использования,

Дайте мне страны, где друзья Джорджа живут

Это может затем быть сделано путем огранки.Вы можете запросить

  • для ID Джорджа
  • фасета countryRaw

Такой запрос будет выглядеть q=friends:1&rows=0&facet=true&facet.field=countryRaw&facet.mincount=1

все документы (лица), чей друг 30 лет.

Это сложнее. Сначала вам понадобится Solr's join feature. Вам необходимо настроить это в файле solrconfig.xml.

<config> 
    <!-- loads of other stuff --> 
    <queryParser name="join" class="org.apache.solr.search.JoinQParserPlugin" /> 
    <!-- loads of other stuff --> 
</config> 

Предос- присоединиться запрос будет выглядеть следующим образом q={!join from=id to=friends}age:[30 TO *]

Это объясняется следующим

  • с age:[30 TO *] вы поиск для всех лиц, которые в возрасте 30 лет или старше
  • тогда вы принимаете их id и присоединитесь к ним в друзьях всех остальных
  • это вернет вам всех людей, которые hav e идентификаторы, соответствующие исходному запросу в их атрибуте друзей

Как я еще не написал это, вы можете посмотреть мой проект solrsample на github. Я добавил тест, что там дело о вопросе:

https://github.com/chriseverty/solrsample/blob/master/src/main/java/de/cheffe/solrsample/FriendJoinTest.java

+0

Cheffe, Спасибо, что ответили на ваш вопрос. Но, возможно, я не особо подчеркивал, что схема не должна изменяться. Предположим, что схема указана. Можете ли вы найти какое-либо возможное решение о том, как можно получить доступ к указанным данным? – user1949763

+0

user1949763, В этом случае мне нужно больше вашего schema.xml. В лучшем случае весь элемент '' включая ваши 'types'. – cheffe

+0

Я добавил 'schema.xml'definition к исходному сообщению. Но определения довольно расплывчаты, потому что я не смог преодолеть ограничение ... – user1949763

Смежные вопросы