Spring Data MongoDB Remove _class Column

By default, SpringData’s MappingMongoConverter add an extra “_class” column for every object saved in MongoDB. For example,

public class User {
 
	String username;
	String password;
 
	//...getters and setters
}

Save it

    MongoOperations mongoOperation = (MongoOperations)ctx.getBean("mongoTemplate");	
    User user = new User("mkyong", "password123");
    mongoOperation.save(user, "users");

Result

> db.users.find()
{ 
	"_class" : "com.mkyong.user.User", 
	"_id" : ObjectId("5050aef830041f24ff2bd16e"), 
	"password" : "new password", "username" : "mkyong" 
}

SpringData created this extra “_class” for a reason. To remove this extra “_class“, override the MappingMongoConverter, and passing a new DefaultMongoTypeMapper(null).

Here we show you how to remove the _class in annotation or XML way.

1. Annotation

@Configuration
public class SpringMongoConfig{
 
  public @Bean
  MongoDbFactory mongoDbFactory() throws Exception {
	return new SimpleMongoDbFactory(new Mongo(), "database");
  }
 
  public @Bean
  MongoTemplate mongoTemplate() throws Exception {
 
	//remove _class
	MappingMongoConverter converter = 
		new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
	converter.setTypeMapper(new DefaultMongoTypeMapper(null));
 
	MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);
 
	return mongoTemplate;
 
  }
 
}

2. XML

Same thing, but in XML file.

<mongo:mongo host="localhost" port="27017" />
<mongo:db-factory dbname="database" />
 
 <bean id="mappingContext"
	class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
 
 <bean id="defaultMongoTypeMapper"
	class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
	<constructor-arg name="typeKey"><null/></constructor-arg>
 </bean>
 
 <bean id="mappingMongoConverter"
	class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
	<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
	<constructor-arg name="mappingContext" ref="mappingContext" />
	<property name="typeMapper" ref="defaultMongoTypeMapper" />
 </bean>
 
 <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
	<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
	<constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
 </bean>

3. Test it Again

Save it again, the “_class” is gone.

> db.users.find()
{ 
	"_id" : ObjectId("random code"), 
	"password" : "new password", "username" : "mkyong" 
}

References

  1. StackOverflow – MappingMongoConverter remove _class
  2. Spring Forum – MappingMongoConverter remove _class



출처 - http://www.mkyong.com/mongodb/spring-data-mongodb-remove-_class-column/




Posted by linuxism
,


Detect mobile browser (smartphone)

Detecting mobile browsers is very easy when you know the right regular expression.

Here are two examples (for PHP and JSP)

PHP

<?php
$useragent = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i',substr($useragent,0,4)))
 
header('Location: http://mysite.com/mobile_version');
?>

JAVA (JSP)

<%
String ua=request.getHeader("User-Agent").toLowerCase();
 
if (ua.matches(".*(android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino).*")||ua.substring(0,4).matches("1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|e\\-|e\\/|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\\-|2|g)|yas\\-|your|zeto|zte\\-"))
 
response.sendRedirect("http://mysite.com/mobile_version");
%>

More info HERE.



출처 - http://www.serveradminblog.com/2011/01/detect-mobile-browser-smartphone/






<%
 // 헤더에서 스마트폰 여부확인 후 리다이렉트
 String browser = request.getHeader("User-Agent");                    // 브라우저 구해오기
 boolean result = false;
 if (browser.indexOf("Android") > 0) {                                        // 안드로이드로 접속했다면 결과값 true
  result = true;
 } else if (browser.indexOf("iPhone") > 0) {                               // 아이폰으로 접속했다면 결과값 true
  result = true;
 }

 if (result == true) {
  response.sendRedirect("http://m.naver.com");                         // 안드로이드나 아이폰으로 접속했다면 모바일사이트로 이동
 } 
%>



출처 - http://blog.naver.com/PostView.nhn?blogId=50english&logNo=40124085444&redirect=Dlog&widgetTypeCall=true





Posted by linuxism
,


정규표현식과 매치 되지 않는 정보 조회(mongodb regex not match)

where("scope").is(0).not().and("readers").not().regex(userID)






How to code with Spring data MongoDB for db.test.update({name:'abc'}, {$pull: {'child': {'age':10}}})


From console, I can operate as db.test.update({name:'abc'}, {$pull: {'child': {'age':10}}}).

How to code with spring-data-mongodb in Java for this instruction? I got mongoTemplate. I know I need to invoke Update.pull(). But I don't know the details.

Thanks for your response.

share|improve this question
update.pull("child", new BasicDBObject("age", 10));

mongoOperation.updateMulti(query, update, collectionName);
share|improve this answer
+1. I think this should help. – Ankur Aug 9 at 7:07



출처 - http://stackoverflow.com/questions/18140739/how-to-code-with-spring-data-mongodb-for-db-test-updatenameabc-pull








find one/several column(s) in a collection


Can i use mongoTemplate or other class/interface to find one/several column(s) in a collection?

For example, if i want to get only the name from collection: users(name, password, age, email) , how could i do?

share|improve this question

You can specify the fields returned by the query with Query.fields() method.

So in your case, assuming that user collection is mapped to User class the query could look like this:

Query query =new Query(whatever criteria you have);
query.fields().include("name");
List<User> list = template.find(query, User.class);

Another way would be o extends a MongoRepository and specify fields qith Queryannotation:

public interface UserRepository extends MongoRepository<User, String> {

   @Query(fields="{ 'name' : 1}")
   List<User> findUserNames();

}

findUserNames should return User instances with only name and id fields initialized.

edit

By the looks of it spring-data-mongo doesn't have a converter to String registered so you have to either retrieve User with all the fields except the ones included in the query set to null or create and register a converter.

share|improve this answer



출처 - http://stackoverflow.com/questions/12949870/spring-mongotemplate-find-special-column







Thursday, May 9, 2013

Simple Pagination for MongoDB Queries Using QueryDSL

So, I have looked at several Java APIs for MongoDB integration; my favorite by far is Spring Data.  That said, Spring has API classes for paging and sorting.  Even with those classes, I find theQueryDSL API from mysema to be very functional.  To work with my Maven projects, I add the below plugin and dependencies:

...<plugin>
    <groupId>com.mysema.maven</groupId>
    <artifactId>maven-apt-plugin</artifactId>
    <version>1.0</version>
    <executions>
     <execution>
      <goals>
       <goal>process</goal>
      </goals>
      <configuration>
       <outputDirectory>target/generated-sources/java</outputDirectory>
       <processor>com.mysema.query.apt.QuerydslAnnotationProcessor</processor>
      </configuration>
     </execution>
    </executions>
   </plugin>
...
<dependency>
   <groupId>com.mysema.querydsl</groupId>
   <artifactId>querydsl-apt</artifactId>
   <version>2.2.3</version>
  </dependency>
  <dependency>
   <groupId>com.mysema.querydsl</groupId>
   <artifactId>querydsl-mongodb</artifactId>
   <version>2.2.3</version>
  </dependency>
...
Once my Maven configuration is set, I need to update the domain model objects that I will be using with QueryDSL.  Below is a snippet from my Employee model object with the @QueryEntityannotation added:


...
@QueryEntity
@Document(collection = "employees")
public class Employee extends Person {
...

Next I need to update the Spring Data Employee Repository interface to extend the QueryDslPredicateExecutor interface, type by my Employee model class.  At this point it is important to note that for the this integration, I had to switch from the annotated Mongo Repository definition to extending   the MongoRepository interface.  The @RepositoryDefinitionannotation did not want to play nice with the QueryDslPredicateExecutor extension.


...
// @RepositoryDefinition(domainClass = Employee.class, idClass = String.class)
public interface EmployeeRepository extends MongoRepository<Employee, String>,
  QueryDslPredicateExecutor<Employee> {
...
Next, I need to update my EmployeeService interface and EmployeeServiceImpl implementation class to add a new method to access the generated find...() methods added for me by QueryDSL.


...
 public Page<Employee> findAllWithPages(int pageStart, int pageSize,
   Sort.Direction sortDirection, String sortField) {
  PageRequest pageRequest = new PageRequest(pageStart, pageSize,
    new Sort(Sort.Direction.ASC, "employeeId"));
  return this.employeeRepository.findAll(pageRequest);
 }
...
In this new method, I build a org.springframework.data.domain.PageRequest object and a org.springframework.data.domain.Sort object to pass into the newly provisioned findAll(..) method on the EmployeeRepository.  I did not write this new findAll(...) method, it was generated for me by QueryDSL and Spring Data.  Additionally, QueryDSL created the QEmployee class for me and placed it into target/generated-soutces/java in my Maven project.  QEmployee is a query type and is seen in its entirety below.


import static com.mysema.query.types.PathMetadataFactory.*;
 
import com.mysema.query.types.*;
import com.mysema.query.types.path.*;
 
 
/**
 * QEmployee is a Querydsl query type for Employee
 */
public class QEmployee extends EntityPathBase<Employee> {
 
    private static final long serialVersionUID = -236647047;
 
    public static final QEmployee employee = new QEmployee("employee");
 
    public final QPerson _super = new QPerson(this);
 
    public final SimplePath<Address> address = createSimple("address", Address.class);
 
    //inherited
    public final DateTimePath<java.util.Date> birthDate = _super.birthDate;
 
    public final SimplePath<Department> department = createSimple("department", Department.class);
 
    public final StringPath employeeId = createString("employeeId");
 
    //inherited
    public final StringPath firstName = _super.firstName;
 
    public final DateTimePath<java.util.Date> hireDate = createDateTime("hireDate", java.util.Date.class);
 
    //inherited
    public final StringPath id = _super.id;
 
    //inherited
    public final StringPath lastName = _super.lastName;
 
    //inherited
    public final StringPath middleName = _super.middleName;
 
    public final NumberPath<Integer> salary = createNumber("salary", Integer.class);
 
    public final StringPath title = createString("title");
 
    public QEmployee(String variable) {
        super(Employee.class, forVariable(variable));
    }
 
    public QEmployee(BeanPath<? extends Employee> entity) {
        super(entity.getType(), entity.getMetadata());
    }
 
    public QEmployee(PathMetadata<?> metadata) {
        super(Employee.class, metadata);
    }
 
}

Finally, below is the JUnit test that calls the pagination code generated for me. 
package com.icfi.mongo;
 
import static org.junit.Assert.assertEquals;
 
import java.util.List;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
 
import com.icfi.mongo.data.loaders.EmployeeShortLoader;
import com.icfi.mongo.data.model.Employee;
import com.icfi.mongo.services.EmployeeService;
 
public class PagingQueryTest {
 private static Logger log = LoggerFactory.getLogger(PagingQueryTest.class);
 
 private ApplicationContext ctx;
 MongoOperations mongoOps;
 List<Employee> employees;
 EmployeeService employeeService;
 
 @Before
 public void setup() {
  ctx = new GenericXmlApplicationContext("context/main.xml");
  mongoOps = (MongoOperations) ctx.getBean("mongoTemplate");
  employeeService = (EmployeeService) ctx.getBean("employeeService");
  EmployeeShortLoader.main(null);
 }
 
 @Test
 public void testPaging() {
  String[] lastNames = new String[] { "Stanfel", "Gustavson", "Lortz",
    "Marquardt", "Unno", "Savasere", "Spelt", "Wynblatt",
    "Danecki", "Weedman", "Hartvigsen", "Menhoudj", "Heyers",
    "Willoner", "Shumilov", "Zuberek", "Boguraev" };
  int pageCount = 10;
  int pageNumber = 0;
  String sortField = "employeeId";
  Sort.Direction sortOrder = Sort.Direction.ASC;
 
  Page<Employee> employeesPage = employeeService.findAllWithPages(
    pageNumber, pageCount, sortOrder, sortField);
 
  while (employeesPage.hasNextPage()) {
 
   assertEquals("List size is incorrect.", pageCount,
     employeesPage.getSize());
 
   log.info("Page Number = " + pageNumber);
 
   if (employeesPage.hasContent()) {
    log.info(employeesPage.getContent()
      .get(employeesPage.getSize() - 1).getLastName());
 
    assertEquals(
      "Last name was incorrect.",
      lastNames[pageNumber],
      employeesPage.getContent()
        .get(employeesPage.getSize() - 1).getLastName());
   }
 
   pageNumber++;
 
   employeesPage = employeeService.findAllWithPages(pageNumber,
     pageCount, sortOrder, sortField);
  }
 
  log.info("Page Number = " + pageNumber);
 
  employeesPage = employeeService.findAllWithPages(pageNumber, pageCount,
    sortOrder, sortField);
 
  log.info(employeesPage.getContent()
    .get(employeesPage.getContent().size() - 1).getLastName());
 
  assertEquals(
    "Last name was incorrect.",
    lastNames[pageNumber],
    employeesPage.getContent()
      .get(employeesPage.getContent().size() - 1)
      .getLastName());
 }
 
 @After
 public void tearDown() {
  this.mongoOps.getCollection("employees").drop();
 }
}

With this approach I have quickly added pagination to my MongoDB queries, while writing minimal code.


출처 - http://jimmyraywv.blogspot.kr/2013/05/simple-pagination-for-mongodb-queries.html








Spring Data MongoDB : Update Document

In Spring data – MongoDB, you can use following methods to update documents.

  1. save – Update the whole object, if “_id” is present, perform an update, else insert it.
  2. updateFirst – Updates the first document that matches the query.
  3. updateMulti – Updates all documents that match the query.
  4. Upserting – If no document that matches the query, a new document is created by combining the query and update object.
  5. findAndModify – Same with updateMulti, but it has an extra option to return either the old or newly updated document.

P.S All examples are tested under mongo-java-driver-2.11.0.jar and spring-data-mongodb-1.2.0.RELEASE.jar

1. saveOrUpdate – part 1 example

Assume below json data is inserted into MongoDB.

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1001", 
	"name" : "appleA", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T23:17:35.530Z") 
}

Find the document, modify and update it with save() method.

	Query query = new Query();
	query.addCriteria(Criteria.where("name").is("appleA"));
 
	User userTest1 = mongoOperation.findOne(query, User.class);
 
	System.out.println("userTest1 - " + userTest1);
 
	//modify and update with save()
	userTest1.setAge(99);
	mongoOperation.save(userTest1);
 
	//get the updated object again
	User userTest1_1 = mongoOperation.findOne(query, User.class);
 
	System.out.println("userTest1_1 - " + userTest1_1);

Output

userTest1 - User [id=id, ic=1001, name=appleA, age=20, createdDate=Sat Apr 06 23:17:35 MYT 2013]
userTest1_1 - User [id=id, ic=1001, name=appleA, age=99, createdDate=Sat Apr 06 23:17:35 MYT 2013]
Note
See example 2, it shows a common mistake made by most of the developers.

2. saveOrUpdate - part 2 example

This is a failed example, read carefully, a really common mistake.

Assume below json data is inserted into MongoDB.

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1002", 
	"name" : "appleB", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}

In Query, you get the document returned with a single "name" field value only, it did happened often to save the object returned size. The returned "User" object has null value in the fields : age, ic and createdDate, if you modify the 'age' field and update it, it will override everything instead of update the modified field - 'age'.

		Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleB"));
		query.fields().include("name");
 
		User userTest2 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest2 - " + userTest2);
 
		userTest2.setAge(99);
 
		mongoOperation.save(userTest2);
 
		// ooppss, you just override everything, it caused ic=null and
		// createdDate=null
 
		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleB"));
 
		User userTest2_1 = mongoOperation.findOne(query1, User.class);
		System.out.println("userTest2_1 - " + userTest2_1);

Output

userTest2 - User [id=51603dba3004d7fffc202391, ic=null, name=appleB, age=0, createdDate=null]
userTest2_1 - User [id=51603dba3004d7fffc202391, ic=null, name=appleB, age=99, createdDate=null]

After the save(), the field 'age' is updated correctly, but ic and createdDate are both set to null, the entire "user" object is updated. To update a single field / key value, don't use save(), use updateFirst() or updateMulti() instead.

3. updateFirst example

Updates the first document that matches the query. In this case, only the single field "age" is updated.

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1003", 
	"name" : "appleC", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T23:22:34.530Z") 
}
		//returns only 'name' field
		Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleC"));
		query.fields().include("name");
 
		User userTest3 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest3 - " + userTest3);
 
		Update update = new Update();
		update.set("age", 100);
 
		mongoOperation.updateFirst(query, update, User.class);
 
		//returns everything
		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleC"));
 
		User userTest3_1 = mongoOperation.findOne(query1, User.class);
		System.out.println("userTest3_1 - " + userTest3_1);

Output

userTest3 - User [id=id, ic=null, name=appleC, age=0, createdDate=null]
userTest3_1 - User [id=id, ic=1003, name=appleC, age=100, createdDate=Sat Apr 06 23:22:34 MYT 2013]

4. updateMulti example

Updates all documents that matches the query.

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1004", 
	"name" : "appleD", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}
{ 
	"_id" : ObjectId("id"), 
	"ic" : "1005", 
	"name" : "appleE", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}
		//show the use of $or operator
		Query query = new Query();
		query.addCriteria(Criteria
				.where("name").exists(true)
				.orOperator(Criteria.where("name").is("appleD"),
						Criteria.where("name").is("appleE")));
		Update update = new Update();
 
		//update age to 11
		update.set("age", 11);
 
		//remove the createdDate field
		update.unset("createdDate");
 
		// if use updateFirst, it will update 1004 only.
		// mongoOperation.updateFirst(query4, update4, User.class);
 
		// update all matched, both 1004 and 1005
		mongoOperation.updateMulti(query, update, User.class);
 
		System.out.println(query.toString());
 
		List<User> usersTest4 = mongoOperation.find(query4, User.class);
 
		for (User userTest4 : usersTest4) {
			System.out.println("userTest4 - " + userTest4);
		}

Output

Query: { "name" : { "$exists" : true} , 
	"$or" : [ { "name" : "appleD"} , { "name" : "appleE"}]}, Fields: null, Sort: null
 
userTest4 - User [id=id, ic=1004, name=appleD, age=11, createdDate=null]
userTest4 - User [id=id, ic=1005, name=appleE, age=11, createdDate=null]

5. Upsert example

If document is matched, update it, else create a new document by combining the query and update object, it's works likefindAndModifyElseCreate() :)

{ 
	//no data
}
		//search a document that doesn't exist
		Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleZ"));
 
		Update update = new Update();
		update.set("age", 21);
 
		mongoOperation.upsert(query, update, User.class);
 
		User userTest5 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest5 - " + userTest5);

Output, a new document is created by combining both query and update object.

userTest5 - User [id=id, ic=null, name=appleZ, age=21, createdDate=null]

6. findAndModify example

Find and modify and get the newly updated object from a single operation.

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1006", 
	"name" : "appleF", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-07T13:11:34.530Z") 
}
		Query query6 = new Query();
		query6.addCriteria(Criteria.where("name").is("appleF"));
 
		Update update6 = new Update();
		update6.set("age", 101);
		update6.set("ic", 1111);
 
		//FindAndModifyOptions().returnNew(true) = newly updated document
		//FindAndModifyOptions().returnNew(false) = old document (not update yet)
		User userTest6 = mongoOperation.findAndModify(
				query6, update6, 
				new FindAndModifyOptions().returnNew(true), User.class);
		System.out.println("userTest6 - " + userTest6);

Output

userTest6 - User [id=id, ic=1111, name=appleF, age=101, createdDate=Sun Apr 07 13:11:34 MYT 2013]

7. Full example

Full application to combine everything from example 1 to 6.

package com.mkyong.core;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
 
import com.mkyong.config.SpringMongoConfig;
import com.mkyong.model.User;
 
public class UpdateApp {
 
	public static void main(String[] args) {
		// For Annotation
		ApplicationContext ctx = 
			new AnnotationConfigApplicationContext(SpringMongoConfig.class);
		MongoOperations mongoOperation = 
			(MongoOperations) ctx.getBean("mongoTemplate");
 
		// insert 6 users for testing
		List<User> users = new ArrayList<User>();
 
		User user1 = new User("1001", "appleA", 20, new Date());
		User user2 = new User("1002", "appleB", 20, new Date());
		User user3 = new User("1003", "appleC", 20, new Date());
		User user4 = new User("1004", "appleD", 20, new Date());
		User user5 = new User("1005", "appleE", 20, new Date());
		User user6 = new User("1006", "appleF", 20, new Date());
		users.add(user1);
		users.add(user2);
		users.add(user3);
		users.add(user4);
		users.add(user5);
		users.add(user6);
		mongoOperation.insert(users, User.class);
 
		// Case 1 ... find and update
		System.out.println("Case 1");
 
		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleA"));
 
		User userTest1 = mongoOperation.findOne(query1, User.class);
 
		System.out.println("userTest1 - " + userTest1);
 
		userTest1.setAge(99);
		mongoOperation.save(userTest1);
 
		User userTest1_1 = mongoOperation.findOne(query1, User.class);
 
		System.out.println("userTest1_1 - " + userTest1_1);
 
		// Case 2 ... select single field only
		System.out.println("\nCase 2");
 
		Query query2 = new Query();
		query2.addCriteria(Criteria.where("name").is("appleB"));
		query2.fields().include("name");
 
		User userTest2 = mongoOperation.findOne(query2, User.class);
		System.out.println("userTest2 - " + userTest2);
 
		userTest2.setAge(99);
 
		mongoOperation.save(userTest2);
 
		// ooppss, you just override everything, it caused ic=null and
		// createdDate=null
 
		Query query2_1 = new Query();
		query2_1.addCriteria(Criteria.where("name").is("appleB"));
 
		User userTest2_1 = mongoOperation.findOne(query2_1, User.class);
		System.out.println("userTest2_1 - " + userTest2_1);
 
		System.out.println("\nCase 3");
		Query query3 = new Query();
		query3.addCriteria(Criteria.where("name").is("appleC"));
		query3.fields().include("name");
 
		User userTest3 = mongoOperation.findOne(query3, User.class);
		System.out.println("userTest3 - " + userTest3);
 
		Update update3 = new Update();
		update3.set("age", 100);
 
		mongoOperation.updateFirst(query3, update3, User.class);
 
		Query query3_1 = new Query();
		query3_1.addCriteria(Criteria.where("name").is("appleC"));
 
		User userTest3_1 = mongoOperation.findOne(query3_1, User.class);
		System.out.println("userTest3_1 - " + userTest3_1);
 
		System.out.println("\nCase 4");
		Query query4 = new Query();
		query4.addCriteria(Criteria
				.where("name")
				.exists(true)
				.orOperator(Criteria.where("name").is("appleD"),
						Criteria.where("name").is("appleE")));
		Update update4 = new Update();
		update4.set("age", 11);
		update4.unset("createdDate");
 
		// update 1004 only.
		// mongoOperation.updateFirst(query4, update4, User.class);
 
		// update all matched
		mongoOperation.updateMulti(query4, update4, User.class);
 
		System.out.println(query4.toString());
 
		List<User> usersTest4 = mongoOperation.find(query4, User.class);
 
		for (User userTest4 : usersTest4) {
			System.out.println("userTest4 - " + userTest4);
		}
 
		System.out.println("\nCase 5");
		Query query5 = new Query();
		query5.addCriteria(Criteria.where("name").is("appleZ"));
 
		Update update5 = new Update();
		update5.set("age", 21);
 
		mongoOperation.upsert(query5, update5, User.class);
 
		User userTest5 = mongoOperation.findOne(query5, User.class);
		System.out.println("userTest5 - " + userTest5);
 
		System.out.println("\nCase 6");
		Query query6 = new Query();
		query6.addCriteria(Criteria.where("name").is("appleF"));
 
		Update update6 = new Update();
		update6.set("age", 101);
		update6.set("ic", 1111);
 
		User userTest6 = mongoOperation.findAndModify(query6, update6,
				new FindAndModifyOptions().returnNew(true), User.class);
		System.out.println("userTest6 - " + userTest6);
 
		mongoOperation.dropCollection(User.class);
 
	}
 
}

Output

Case 1
userTest1 - User [id=id, ic=1001, name=appleA, age=20, createdDate=Sun Apr 07 13:22:48 MYT 2013]
userTest1_1 - User [id=id, ic=1001, name=appleA, age=99, createdDate=Sun Apr 07 13:22:48 MYT 2013]
 
Case 2
userTest2 - User [id=id, ic=null, name=appleB, age=0, createdDate=null]
userTest2_1 - User [id=id, ic=null, name=appleB, age=99, createdDate=null]
 
Case 3
userTest3 - User [id=id, ic=null, name=appleC, age=0, createdDate=null]
userTest3_1 - User [id=id, ic=1003, name=appleC, age=100, createdDate=Sun Apr 07 13:22:48 MYT 2013]
 
Case 4
Query: { "name" : { "$exists" : true} , "$or" : [ { "name" : "appleD"} , { "name" : "appleE"}]}, Fields: null, Sort: null
userTest4 - User [id=id, ic=1004, name=appleD, age=11, createdDate=null]
userTest4 - User [id=id, ic=1005, name=appleE, age=11, createdDate=null]
 
Case 5
userTest5 - User [id=id, ic=null, name=appleZ, age=21, createdDate=null]
 
Case 6
userTest6 - User [id=id, ic=1006, name=appleF, age=20, createdDate=Sun Apr 07 13:22:48 MYT 2013]


출처 - http://www.mkyong.com/mongodb/spring-data-mongodb-update-document/








Here we show you a few examples to query documents from MongoDB, by using Query, Criteria and along with some of the common operators.

Test Data

> db.users.find()
{ "_id" : ObjectId("id"), "ic" : "1001", "name" : "ant", "age" : 10 }
{ "_id" : ObjectId("id"), "ic" : "1002", "name" : "bird", "age" : 20 }
{ "_id" : ObjectId("id"), "ic" : "1003", "name" : "cat", "age" : 30 }
{ "_id" : ObjectId("id"), "ic" : "1004", "name" : "dog", "age" : 40 }
{ "_id" : ObjectId("id"), "ic" : "1005", "name" : "elephant", "age" : 50 }
{ "_id" : ObjectId("id"), "ic" : "1006", "name" : "frog", "age" : 60 }

P.S This example is tested under mongo-java-driver-2.11.0.jar and spring-data-mongodb-1.2.0.RELEASE.jar


1. BasicQuery example

If you are familiar with the core MongoDB console find() command, just put the “raw” query inside the BasicQuery.

BasicQuery query1 = new BasicQuery("{ age : { $lt : 40 }, name : 'cat' }");
User userTest1 = mongoOperation.findOne(query1, User.class);
 
System.out.println("query1 - " + query1.toString());
System.out.println("userTest1 - " + userTest1);

Output

query1 - Query: { "age" : { "$lt" : 40} , "name" : "cat"}, Fields: null, Sort: { }
userTest1 - User [id=id, ic=1003, name=cat, age=30]

2. findOne example

findOne will return the single document that matches the query, and you can a combine few criteria with Criteria.and()method. See example 4 for more details.

Query query2 = new Query();
query2.addCriteria(Criteria.where("name").is("dog").and("age").is(40));
 
User userTest2 = mongoOperation.findOne(query2, User.class);
System.out.println("query2 - " + query2.toString());
System.out.println("userTest2 - " + userTest2);

Output

query2 - Query: { "name" : "dog" , "age" : 40}, Fields: null, Sort: null
userTest2 - User [id=id, ic=1004, name=dog, age=40]

3. find and $inc example

Find and return a list of documents that match the query. This example also shows the use of $inc operator.

List<Integer> listOfAge = new ArrayList<Integer>();
listOfAge.add(10);
listOfAge.add(30);
listOfAge.add(40);
 
Query query3 = new Query();
query3.addCriteria(Criteria.where("age").in(listOfAge));
 
List<User> userTest3 = mongoOperation.find(query3, User.class);
System.out.println("query3 - " + query3.toString());
 
for (User user : userTest3) {
	System.out.println("userTest3 - " + user);
}

Output

query3 - Query: { "age" : { "$in" : [ 10 , 30 , 40]}}, Fields: null, Sort: null
userTest3 - User [id=id, ic=1001, name=ant, age=10]
userTest3 - User [id=id, ic=1003, name=cat, age=30]
userTest3 - User [id=id, ic=1004, name=dog, age=40]

4. find and $gt, $lt, $and example

Find and return a list of documents that match the query. This example also shows the use of $gt$lt and $andoperators.

Query query4 = new Query();
query4.addCriteria(Criteria.where("age").lt(40).and("age").gt(10));
 
List<User> userTest4 = mongoOperation.find(query4, User.class);
System.out.println("query4 - " + query4.toString());
 
for (User user : userTest4) {
	System.out.println("userTest4 - " + user);
}

Oppss, an error message is generated, the API doen’t works in this way :)

Due to limitations of the com.mongodb.BasicDBObject, you can't add a second 'age' expression 
specified as 'age : { "$gt" : 10}'. Criteria already contains 'age : { "$lt" : 40}'.

You can’t use Criteria.and() to add multiple criteria into the same field, to fix it, use Criteria.andOperator(), see updated example :

Query query4 = new Query();
query4.addCriteria(
	Criteria.where("age").exists(true)
	.andOperator(
		Criteria.where("age").gt(10),
                Criteria.where("age").lt(40)
	)
);
 
List<User> userTest4 = mongoOperation.find(query4, User.class);
System.out.println("query4 - " + query4.toString());
 
for (User user : userTest4) {
	System.out.println("userTest4 - " + user);
}

Output

query4 - Query: { "age" : { "$lt" : 40} , "$and" : [ { "age" : { "$gt" : 10}}]}, Fields: null, Sort: null
userTest4 - User [id=51627a0a3004cc5c0af72964, ic=1002, name=bird, age=20]
userTest4 - User [id=51627a0a3004cc5c0af72965, ic=1003, name=cat, age=30]

5. find and sorting example

Find and sort the result.

Query query5 = new Query();
query5.addCriteria(Criteria.where("age").gte(30));
query5.with(new Sort(Sort.Direction.DESC, "age"));
 
List<User> userTest5 = mongoOperation.find(query5, User.class);
System.out.println("query5 - " + query5.toString());
 
for (User user : userTest5) {
	System.out.println("userTest5 - " + user);
}

Output

query5 - Query: { "age" : { "$gte" : 30}}, Fields: null, Sort: { "age" : -1}
userTest5 - User [id=id, ic=1006, name=frog, age=60]
userTest5 - User [id=id, ic=1005, name=elephant, age=50]
userTest5 - User [id=id, ic=1004, name=dog, age=40]
userTest5 - User [id=id, ic=1003, name=cat, age=30]

6. find and $regex example

Find by regular expression pattern.

Query query6 = new Query();
query6.addCriteria(Criteria.where("name").regex("D.*G", "i"));
 
List<User> userTest6 = mongoOperation.find(query6, User.class);
System.out.println("query6 - " + query6.toString());
 
for (User user : userTest6) {
	System.out.println("userTest6 - " + user);
}

Output

query6 - Query: { "name" : { "$regex" : "D.*G" , "$options" : "i"}}, Fields: null, Sort: null
userTest6 - User [id=id, ic=1004, name=dog, age=40]

7. Full Example

A full example to combine everything from example 1 to 6.

SpringMongoConfig.java
package com.mkyong.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
 
import com.mongodb.MongoClient;
 
/**
 * Spring MongoDB configuration file
 * 
 */
@Configuration
public class SpringMongoConfig{
 
	public @Bean
	MongoTemplate mongoTemplate() throws Exception {
 
		MongoTemplate mongoTemplate = 
		    new MongoTemplate(new MongoClient("127.0.0.1"),"yourdb");
		return mongoTemplate;
 
	}
 
}
User.java
package com.mkyong.model;
 
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
 
@Document(collection = "users")
public class User {
 
	@Id
	private String id;
 
	@Indexed
	private String ic;
 
	private String name;	
 
	private int age;
 
	//getter, setter and constructor methods
 
}
QueryApp.java
package com.mkyong.core;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
 
import com.mkyong.config.SpringMongoConfig;
import com.mkyong.model.User;
 
/**
 * Query example
 * 
 * @author mkyong
 * 
 */
public class QueryApp {
 
	public static void main(String[] args) {
 
		ApplicationContext ctx = 
                         new AnnotationConfigApplicationContext(SpringMongoConfig.class);
		MongoOperations mongoOperation = 
                         (MongoOperations) ctx.getBean("mongoTemplate");
 
		// insert 6 users for testing
		List<User> users = new ArrayList<User>();
 
		User user1 = new User("1001", "ant", 10);
		User user2 = new User("1002", "bird", 20);
		User user3 = new User("1003", "cat", 30);
		User user4 = new User("1004", "dog", 40);
		User user5 = new User("1005", "elephant",50);
		User user6 = new User("1006", "frog", 60);
		users.add(user1);
		users.add(user2);
		users.add(user3);
		users.add(user4);
		users.add(user5);
		users.add(user6);
		mongoOperation.insert(users, User.class);
 
		System.out.println("Case 1 - find with BasicQuery example");
 
		BasicQuery query1 = new BasicQuery("{ age : { $lt : 40 }, name : 'cat' }");
		User userTest1 = mongoOperation.findOne(query1, User.class);
 
		System.out.println("query1 - " + query1.toString());
		System.out.println("userTest1 - " + userTest1);
 
		System.out.println("\nCase 2 - find example");
 
		Query query2 = new Query();
		query2.addCriteria(Criteria.where("name").is("dog").and("age").is(40));
 
		User userTest2 = mongoOperation.findOne(query2, User.class);
		System.out.println("query2 - " + query2.toString());
		System.out.println("userTest2 - " + userTest2);
 
		System.out.println("\nCase 3 - find list $inc example");
 
		List<Integer> listOfAge = new ArrayList<Integer>();
		listOfAge.add(10);
		listOfAge.add(30);
		listOfAge.add(40);
 
		Query query3 = new Query();
		query3.addCriteria(Criteria.where("age").in(listOfAge));
 
		List<User> userTest3 = mongoOperation.find(query3, User.class);
		System.out.println("query3 - " + query3.toString());
 
		for (User user : userTest3) {
			System.out.println("userTest3 - " + user);
		}
 
		System.out.println("\nCase 4 - find list $and $lt, $gt example");
 
		Query query4 = new Query();
 
		// it hits error
		// query4.addCriteria(Criteria.where("age").lt(40).and("age").gt(10));
 
		query4.addCriteria(
                   Criteria.where("age").exists(true).andOperator(
		         Criteria.where("age").gt(10),
                         Criteria.where("age").lt(40)
	            )
                );
 
		List<User> userTest4 = mongoOperation.find(query4, User.class);
		System.out.println("query4 - " + query4.toString());
 
		for (User user : userTest4) {
			System.out.println("userTest4 - " + user);
		}
 
		System.out.println("\nCase 5 - find list and sorting example");
		Query query5 = new Query();
		query5.addCriteria(Criteria.where("age").gte(30));
		query5.with(new Sort(Sort.Direction.DESC, "age"));
 
		List<User> userTest5 = mongoOperation.find(query5, User.class);
		System.out.println("query5 - " + query5.toString());
 
		for (User user : userTest5) {
			System.out.println("userTest5 - " + user);
		}
 
		System.out.println("\nCase 6 - find by regex example");
		Query query6 = new Query();
		query6.addCriteria(Criteria.where("name").regex("D.*G", "i"));
 
		List<User> userTest6 = mongoOperation.find(query6, User.class);
		System.out.println("query6 - " + query6.toString());
 
		for (User user : userTest6) {
			System.out.println("userTest6 - " + user);
		}
 
		mongoOperation.dropCollection(User.class);
 
	}
 
}

Output

Case 1 - find with BasicQuery example
query1 - Query: { "age" : { "$lt" : 40} , "name" : "cat"}, Fields: null, Sort: { }
userTest1 - User [id=id, ic=1003, name=cat, age=30]
 
Case 2 - find example
query2 - Query: { "name" : "dog" , "age" : 40}, Fields: null, Sort: null
userTest2 - User [id=id, ic=1004, name=dog, age=40]
 
Case 3 - find list $inc example
query3 - Query: { "age" : { "$in" : [ 10 , 30 , 40]}}, Fields: null, Sort: null
userTest3 - User [id=id, ic=1001, name=ant, age=10]
userTest3 - User [id=id, ic=1003, name=cat, age=30]
userTest3 - User [id=id, ic=1004, name=dog, age=40]
 
Case 4 - find list $and $lt, $gt example
query4 - Query: { "age" : { "$lt" : 40} , "$and" : [ { "age" : { "$gt" : 10}}]}, Fields: null, Sort: null
userTest4 - User [id=id, ic=1002, name=bird, age=20]
userTest4 - User [id=id, ic=1003, name=cat, age=30]
 
Case 5 - find list and sorting example
query5 - Query: { "age" : { "$gte" : 30}}, Fields: null, Sort: { "age" : -1}
userTest5 - User [id=id, ic=1006, name=frog, age=60]
userTest5 - User [id=id, ic=1005, name=elephant, age=50]
userTest5 - User [id=id, ic=1004, name=dog, age=40]
userTest5 - User [id=id, ic=1003, name=cat, age=30]
 
Case 6 - find by regex example
query6 - Query: { "name" : { "$regex" : "D.*G" , "$options" : "i"}}, Fields: null, Sort: null
userTest6 - User [id=id, ic=1004, name=dog, age=40]


출처 - http://www.mkyong.com/mongodb/spring-data-mongodb-query-document/








Posted by linuxism
,