I am developing the Spring Boot + MongoDB + spring data mongo + Text search
Example. By taking a reference from link: https://spring.io/blog/2014/07/17/text-search-your-documents-with-spring-data-mongodb, I developed my code, but when I am executing that, it's giving empty resultset. Please help in this scenario. I was expecting to get both results OrderId = 10248 and 10249
, but I got empty.
My developed code: OrderDetails.java
@Document(collection="order-details")
public class OrderDetails {
@Id
private ObjectId id;
//@TextIndexed(weight=2)
@Field("OrderID")
private Integer orderID;
@Field("ProductID")
private Integer productID;
@Field("UnitPrice")
private Double unitPrice;
@Field("Quantity")
private Integer quantity;
@Field("Discount")
private Integer discount;
// setters and getters
}
OrderDetailsService.java
public interface OrderDetailsService {
List<OrderDetails> findAllBy(Integer searchValue);
}
OrderDetailsServiceImpl.java
@Component
public class OrderDetailsServiceImpl implements OrderDetailsService{
@Autowired
private OrderDetailsRepository odRepository;
@Autowired
private MongoOperations mongoOperations;
public List<OrderDetails> findAllBy(Integer searchValue) {
//TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(searchValue);
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("OrderID")
.matchingPhrase(String.valueOf(searchValue));
Query query = TextQuery.queryText(criteria).sortByScore();
List<OrderDetails> orderDetails =mongoOperations.find(query, OrderDetails.class);
return orderDetails;
}
}
MainController.java
@Controller
public class MainController implements CommandLineRunner {
private Logger LOGGER = Logger.getLogger(MainController.class);
@Autowired
private OrderDetailsService odService;
@Override
public void run(String... args) throws Exception {
LOGGER.info("~~ STARTED ~~");
// Find OrderID
List<OrderDetails> orderDetails = odService.findAllBy(102);
LOGGER.info("Order Details Size :"+orderDetails.size());
}
}
And if I use below in model class
@TextIndexed(weight=2)
@Field("OrderID")
private Integer orderID;
I see following error comes.
Caused by: com.mongodb.CommandFailureException: { "serverUsed" : "localhost:27017" , "createdCollectionAutomatically" : false , "numIndexesBefore" : 2 , "errmsg" : "exception: Index with name: OrderDetails_TextIndex already exists with different options" , "code" : 85 , "ok" : 0.0}
at com.mongodb.CommandResult.getException(CommandResult.java:76)
at com.mongodb.CommandResult.throwOnError(CommandResult.java:131)
at com.mongodb.DBCollectionImpl.createIndex(DBCollectionImpl.java:362)
at com.mongodb.DBCollection.createIndex(DBCollection.java:563)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.createIndex(MongoPersistentEntityIndexCreator.java:133)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.checkForAndCreateIndexes(MongoPersistentEntityIndexCreator.java:127)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.checkForIndexes(MongoPersistentEntityIndexCreator.java:119)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.onApplicationEvent(MongoPersistentEntityIndexCreator.java:103)
at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.onApplicationEvent(MongoPersistentEntityIndexCreator.java:45)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:306)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:180)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:140)
at org.springframework.data.mapping.context.AbstractMappingContext.getPersistentEntity(AbstractMappingContext.java:67)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getEntityInformation(MongoRepositoryFactory.java:141)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactory.getTargetRepository(MongoRepositoryFactory.java:83)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:173)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
at org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean.afterPropertiesSet(MongoRepositoryFactoryBean.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
... 40 more
EDIT:
I follow your instructions and I see following error, please guide further
16-04-06 01:30:32.601 DEBUG MongoTemplate - find using query: { "$text" : { "$search" : "\"OrderID\" \"10248\""}} fields: { "score" : { "$meta" : "textScore"}} for class: class com.common.model.OrderDetails in collection: order-details
16-04-06 01:30:32.610 DEBUG MongoDbUtils - Getting Mongo Database name=[boot]
16-04-06 01:30:32.774 DEBUG DirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@37d4349f testClass = OrderDetailsTest, testInstance = com.common.index.OrderDetailsTest@434a63ab, testMethod = test@OrderDetailsTest, testException = org.springframework.data.mongodb.UncategorizedMongoDbException: Unable to execute query: error processing query: ns=boot.order-details limit=0 skip=0
Tree: TEXT : query="OrderID" "10248", language=, tag=NULL
Sort: { score: { $meta: "textScore" } }
Proj: { score: { $meta: "textScore" } }
planner returned error: need exactly one text index for $text query; nested exception is com.mongodb.MongoException: Unable to execute query: error processing query: ns=boot.order-details limit=0 skip=0
Tree: TEXT : query="OrderID" "10248", language=, tag=NULL
Sort: { score: { $meta: "textScore" } }
Proj: { score: { $meta: "textScore" } }
planner returned error: need exactly one text index for $text query, mergedContextConfiguration = [MergedContextConfiguration@6e0f5f7f testClass = OrderDetailsTest, locations = '{classpath:application-config.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class dirties context [false], class mode [null], method dirties context [false].
16-04-06 01:30:33.232 DEBUG DirtiesContextTestExecutionListener - After test class: context [DefaultTestContext@37d4349f testClass = OrderDetailsTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@6e0f5f7f testClass = OrderDetailsTest, locations = '{classpath:application-config.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], dirtiesContext [false].
16-04-06 01:30:33.236 INFO GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@53045c6c: startup date [Wed Apr 06 01:30:28 IST 2016]; root of context hierarchy
16-04-06 01:30:33.237 DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
OrderDetailsRepository.java
public interface OrderDetailsRepository extends CrudRepository<OrderDetails, String>{
List<OrderDetails> findAllBy(TextCriteria criteria);
}
My Junit: OrderDetailsTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-config.xml"})
public class OrderDetailsTest {
@Autowired
private OrderDetailsService odService;
@Test
public void test() {
List<OrderDetails> orderDetails =odService.findAllBy("10248");
System.out.println("Size : ["+ orderDetails +"]");
for (OrderDetails od : orderDetails) {
System.out.println("-------------------------");
System.out.println(od.getDiscount());
System.out.println(od.getOrderId());
System.out.println(od.getProductId());
System.out.println(od.getQuantity());
System.out.println(od.getUnitPrice());
System.out.println(od.getId());
System.out.println("-----------------------------");
}
}
}
Junit error logs:
org.springframework.data.mongodb.UncategorizedMongoDbException: Unable to execute query: error processing query: ns=boot.order-details limit=0 skip=0
Tree: TEXT : query="OrderID" "10248", language=, tag=NULL
Sort: { score: { $meta: "textScore" } }
Proj: { score: { $meta: "textScore" } }
planner returned error: need exactly one text index for $text query; nested exception is com.mongodb.MongoException: Unable to execute query: error processing query: ns=boot.order-details limit=0 skip=0
Tree: TEXT : query="OrderID" "10248", language=, tag=NULL
Sort: { score: { $meta: "textScore" } }
Proj: { score: { $meta: "textScore" } }
planner returned error: need exactly one text index for $text query
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:101)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2075)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1918)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1729)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1712)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:602)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:593)
at com.common.Service.OrderDetailsServiceImpl.findAllBy(OrderDetailsServiceImpl.java:29)
at com.common.index.OrderDetailsTest.test(OrderDetailsTest.java:24)
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:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:70)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.mongodb.MongoException: Unable to execute query: error processing query: ns=boot.order-details limit=0 skip=0
Tree: TEXT : query="OrderID" "10248", language=, tag=NULL
Sort: { score: { $meta: "textScore" } }
Proj: { score: { $meta: "textScore" } }
planner returned error: need exactly one text index for $text query
at com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:246)
at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:224)
at com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:184)
at com.mongodb.QueryResultIterator.<init>(QueryResultIterator.java:62)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:86)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
at com.mongodb.DBCursor._check(DBCursor.java:498)
at com.mongodb.DBCursor._hasNext(DBCursor.java:621)
at com.mongodb.DBCursor.hasNext(DBCursor.java:657)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1904)
... 35 more
Note: boot is my mongodb name.
Please see another EDIT:
db['order-details'].getIndexes()
/* 0 */
{
"0" : {
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "boot.order-details"
}
}
db['order-details'].createIndex({"OrderID" : "text"})
db['order-details'].getIndexes()
{
"0" : {
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "boot.order-details"
},
"1" : {
"v" : 1,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "OrderID_text",
"ns" : "boot.order-details",
"weights" : {
"OrderID" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
}
}