2016-03-11 64 views
1

我正在使用帶有Schemaless Solr的Spring Data Solr。有些點我無法連接:何時以及如何創建模式字段?Spring Data Solr:聲明字段時如何將multiValue設置爲false

The following page states

自動架構人口將檢查您的域名類型,每當應用程序上下文是刷新並填充新的領域,基於性能配置索引。這要求solr以無模式模式運行。

使用@Indexed提供更多詳細信息,如使用特定的solr類型。

它還正好說明捲曲請求:

//捲曲../solr/collection1/schema/fields -X POST -H '內容類型:應用/ JSON'

但是,當我運行一個帶有@Indexed註釋的字段的簡單示例時,我看不到在SOLR上調用的/ schema/fields API。這些字段是如何創建的?

我問的原因是他們似乎是自動創建multiValued = true。我沒有看到@Indexed註釋採用multiValued作爲參數。如何強制Spring Data Solr在創建它們時將這些字段聲明爲非multiValued?

現在,所有這些都是爲了解決我所看到的這個異常。

java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null 
at org.springframework.util.Assert.notNull(Assert.java:115) 
at org.springframework.util.Assert.notNull(Assert.java:126) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:426) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readCollection(MappingSolrConverter.java:601) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:440) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.readValue(MappingSolrConverter.java:412) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$SolrPropertyValueProvider.getPropertyValue(MappingSolrConverter.java:395) 
at org.springframework.data.solr.core.convert.MappingSolrConverter.getValue(MappingSolrConverter.java:206) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:194) 
at org.springframework.data.solr.core.convert.MappingSolrConverter$1.doWithPersistentProperty(MappingSolrConverter.java:186) 
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:309) 
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:186) 
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:174) 
at org.springframework.data.solr.core.convert.MappingSolrConverter.read(MappingSolrConverter.java:149) 
at org.springframework.data.solr.core.SolrTemplate.convertSolrDocumentListToBeans(SolrTemplate.java:560) 
at org.springframework.data.solr.core.SolrTemplate.convertQueryResponseToBeans(SolrTemplate.java:552) 
at org.springframework.data.solr.core.SolrTemplate.createSolrResultPage(SolrTemplate.java:369) 
at org.springframework.data.solr.core.SolrTemplate.doQueryForPage(SolrTemplate.java:300) 
at org.springframework.data.solr.core.SolrTemplate.queryForPage(SolrTemplate.java:308) 
at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:111) 
at org.springframework.data.solr.repository.support.SimpleSolrRepository.findAll(SimpleSolrRepository.java:106) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at 

我的猜測是異常發生是因爲值作爲集合返回?

我試着通過代碼來了解發生了什麼。導致問題的字段是「名稱」,值是[product-1]。嘗試將solr文檔解組爲POJO時發生異常。

首先,我們去下面的方法中:

private <T> T readValue(Object value, TypeInformation<?> type, Object parent) { 
     if (value == null) { 
      return null; 
     } 

     Assert.notNull(type); 
     Class<?> rawType = type.getType(); 
     if (hasCustomReadTarget(value.getClass(), rawType)) { 
      return (T) convert(value, rawType); 
     } 

     Object documentValue = null; 
     if (value instanceof SolrInputField) { 
      documentValue = ((SolrInputField) value).getValue(); 
     } else { 
      documentValue = value; 
     } 

     if (documentValue instanceof Collection) { 
      return (T) readCollection((Collection<?>) documentValue, type, parent); 
     } else if (canConvert(documentValue.getClass(), rawType)) { 
      return (T) convert(documentValue, rawType); 
     } 

     return (T) documentValue; 

    } 

調用此方法時,該值是一個集合,類型爲java.lang.String的。這導致如果(documentValue的instanceof集合)被選擇,這導致進入下面的方法被執行:

 private Object readCollection(Collection<?> source, TypeInformation<?> type, Object parent) { 
     Assert.notNull(type); 

     Class<?> collectionType = type.getType(); 
     if (CollectionUtils.isEmpty(source)) { 
      return source; 
     } 

     collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class; 

     Collection<Object> items; 
     if (type.getType().isArray()) { 
      items = new ArrayList<Object>(); 
     } else { 
      items = CollectionFactory.createCollection(collectionType, source.size()); 
     } 

     TypeInformation<?> componentType = type.getComponentType(); 

     Iterator<?> it = source.iterator(); 
     while (it.hasNext()) { 
      items.add(readValue(it.next(), componentType, parent)); 
     } 

     return type.getType().isArray() ? convertItemsToArrayOfType(type, items) : items; 
    } 

在該方法中,我們最終調用type.getComponentType(),它返回零,並最終導致斷言。 notNull()失敗。

我在這一切中失去了什麼?

我的代碼如下。啓動和配置類:

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
@EnableSolrRepositories(schemaCreationSupport=true, basePackages = { "com.example.solrdata" }, multicoreSupport = true) 
public class Application { 

public static void main(String[] args) { 
    SpringApplication.run(Application.class, args); 
} 
} 

模型類:

@SolrDocument(solrCoreName = "collection1") 
public class Product { 

@Id 
String id; 
@Indexed 
String name; 

public Product(String id, String name) { 
    this.id = id; 
    this.name = name; 
} 

public Product() { 
    super(); 
} 

public String getId() { 
    return id; 
} 

public void setId(String id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
}} 

庫:

public interface ProductRepository extends SolrCrudRepository<Product, String> {} 

測試類:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(Application.class) 
public class SolrProductRepositoryTest { 

@Autowired 
private ProductRepository repo; 

@Before @After 
public void setup(){ 
    repo.deleteAll(); 
} 

@Test 
public void testCRUD() { 
    assertEquals(0, repo.count()); 
    Product product = new Product("1","product-1"); 
    repo.save(product); 
    assertEquals(1, repo.count()); 
    Product product2 = repo.findOne(product.getId()); 
    assertEquals(product2.getName(), product.getName()); 
}} 

最後,我POM:

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.3.3.RELEASE</version> 
</parent> 

<dependencies> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-test</artifactId> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-solr</artifactId> 
    </dependency> 
</dependencies> 
+0

SD-的Solr後只會造成新的領域(多值的情況下,該屬性是收集等)時,這些做尚不存在,它需要服務器以模式少模式運行。仍然有一個模式存在於服務器上。你可以添加一個嗎。 –

+0

你的意思是我應該添加一個模式?我在無模式模式下運行solr,這是我的一個要求。所以,添加一個模式並不是首選路線。現在,如果多值= true行爲是硬編碼的,我該如何避免上述異常? – Klaus

+0

儘管在無模式模式下運行solr並不意味着沒有模式。它在那裏,可能已經用默認值初始化了。只要看看到conf目錄下並打開文件'託管schema'雖然沒有_xml_文件,它包含您的架構信息 –

回答

0

當使用Solr的4.10與默認不幸在solrconfig.xmlJSONResponseWriter使用text/pain作爲內容類型。

<queryResponseWriter name="json" class="solr.JSONResponseWriter"> 
    <str name="content-type">text/plain; charset=UTF-8</str> 
</queryResponseWriter> 

這導致的SolrSchemaRequest內容類型協商默默地失敗並跳過架構更新步驟 - 和Solr默認字段類型在那個地方猜測踢。

設置content-typeapplication/json允許根據bean定義添加字段。

@SolrDocument(solrCoreName = "collection1") 
public static class SomeDomainType { 

    @Indexed @Id 
    String id; 

    @Indexed 
    String indexedStringWithoutType; 

    @Indexed(name = "namedField", type = "string", searchable = false) 
    String justAStoredField; 

    @Indexed 
    List<String> listField; 

    @Indexed(type = "tdouble") 
    Double someDoubleValue; 
} 

以前

{ 
    responseHeader: { 
     status: 0, 
     QTime: 86 
    }, 
    fields: [ 
     { 
      name: "_version_", 
      type: "long", 
      indexed: true, 
      stored: true 
     }, 
     { 
      name: "id", 
      type: "string", 
      multiValued: false, 
      indexed: true, 
      required: true, 
      stored: true, 
      uniqueKey: true 
     } 
    ] 
} 

架構Upate

{ 
    responseHeader: { 
     status: 0, 
     QTime: 1 
    }, 
    fields: [ 
     { 
      name: "_version_", 
      type: "long", 
      indexed: true, 
      stored: true 
     }, 
     { 
      name: "id", 
      type: "string", 
      multiValued: false, 
      indexed: true, 
      required: true, 
      stored: true, 
      uniqueKey: true 
     }, 
     { 
      name: "indexedStringWithoutType", 
      type: "string", 
      multiValued: false, 
      indexed: true, 
      required: false, 
      stored: true 
     }, 
     { 
      name: "listField", 
      type: "string", 
      multiValued: true, 
      indexed: true, 
      required: false, 
      stored: true 
     }, 
     { 
      name: "namedField", 
      type: "string", 
      multiValued: false, 
      indexed: false, 
      required: false, 
      stored: true 
     }, 
     { 
      name: "someDoubleValue", 
      type: "tdouble", 
      multiValued: false, 
      indexed: true, 
      required: false, 
      stored: true 
     } 
    ] 
} 
+0

感謝Christoph的更新。它似乎不適合我。全新solr-4.10.4。以下solrconfig.xml已更改:./solr-4.10.4/example/example-schemaless/solr/collection1/conf/solrconfig.xml。我用「bin/solr -e無模式」啓動solr。 JSONresponseWriter配置爲: application/json;字符集= UTF-8 異常情況相同。 – Klaus

+0

你有運行的樣本可以運行測試用例嗎?礦山通過上面概述的裝配到solrconfig.xml。 –

+0

我上傳了我的示例項目(帶有測試用例):http://expirebox.com/download/cdf6def72b988528f0d2818047ff559d.html。它基本上由我粘貼在上面的作品組成。 – Klaus

相關問題