Schemaless Solr で Spring Data Solr をいじっています。接続できない点がいくつかあります: スキーマ フィールドはいつ、どのように作成されますか?
アプリケーションのコンテキストが更新されるたびに、スキーマの自動作成によりドメイン タイプが検査され、プロパティの構成に基づいて新しいフィールドがインデックスに入力されます。これには、solr をスキーマレス モードで実行する必要があります。
@Indexed を使用して、使用する特定の solr タイプなどの追加の詳細を提供します。
また、curl リクエストも表示されます。
// curl ../solr/collection1/schema/fields -X POST -H 'Content-type:application/json'
ただし、@Indexed で注釈が付けられたフィールドで単純な例を実行すると、SOLR で呼び出されている /schema/fields API が表示されません。これらのフィールドはどのように作成されますか?
私が尋ねている理由は、それらが multiValued=true で自動的に作成されるように見えるからです。multiValued をパラメーターとして取る @Indexed アノテーションは見当たりませんでした。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
値がコレクションとして返されているため、例外が発生していると思いますか?
何が起こっているのかを理解するために、コードをステップ実行しようとしました。問題を引き起こしているフィールドは「name」で、値は [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 です。これにより、if(documentValue instanceof Collection) が選択され、次のメソッドが実行されます。
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() を呼び出します。これは null を返し、最終的に Assert.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>