Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents?...

44
Deep Dive i nto Spring Data and MongoDB Fabiano Guizellini Modos Software Architect at HBSIS @fmodos

Transcript of Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents?...

Page 1: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Deep Dive into

Spring Data and

MongoDBFabiano Guizellini Modos

Software Architect at HBSIS@fmodos

Page 2: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

I Java andMongoDB

Page 3: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Why do I love Java?

• Learned Object OrientedProgramming

• Design Patterns, Clean Code, Unit Test

• Saved me from Programming in Delphi

Page 4: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Why do I love MongoDB?

• Save complex Objects in an easy way

• No more relational databasecommands: Create table, Alter Table, etc..

• Open Source

Page 5: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

It is not only a Story

...run this in Production in 3 critical systems

Page 6: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Order

Invoice

SupermarketOrder

Invoice

Supermarket

Deliver

~5k Suppliers Invoice Daily~4M Events Daily>10M DB Ops/Daily

>100k Sales Invoices Daily>500k Events Daily>10M DB Ops/Daily

~35k Transport Invoice Daily~300k Events Daily>1M DB Ops/Daily

Validate Suppliers Invoice

Sales Invoice

Transport Invoice

Page 7: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Why did we use MongoDB?

• Complex documents and events

• High Concurrency System

Page 8: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Why did we use MongoDB?

• Complex documents and events

• High Concurrency System

Page 9: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Relational Database? SQL?

SQL NOSQL

Page 10: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

“Different databases are designed to solve different problems. Using a single database engine for all of the requirements usually leads to non-performant solutions”― Pramod J. Sadalage, NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence

“Complex applications combine different types of problems, so picking the right language for each job may be more productive than trying to fit all aspects into a single language.” ― Pramod J. Sadalage, NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence

Page 11: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Case Study – Food Recipe System

Class Diagram Table Diagram (SQL) Document Diagram (NoSQL)

• Users should be able to create Dish with a name, description and list of ingredientes• Users should be able to add Comments to the Dish.

Page 12: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Create

SQL NoSQL

INSERT INTO dish (name)VALUES (“White Rice”)

INSERT INTO ingredient (name, dish_id)VALUES (“rice”, 1)

INSERT INTO ingredient (name)VALUES (“garlic”, 1)

INSERT INTO comment (text, user_id, dish_id)VALUES (“This rice is really good”, 1, 1)

db.getCollection(‘Dish’).save({name: “White Rice”ingredients : [“rice”, “garlic”],comments : Array[

{text : ‘This rice is really good’user : {

nickname : ‘FoodLover’,email: ‘[email protected]

}]

})

Page 13: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Read

SQL NoSQL

SELECT d.name, d.description FROM dish d WHERE id=1

SELECT i.name FROM ingredient i WHERE i.dish_id=1

SELECT c.text, u.nickname, u.name FROM comment c, user u WHERE c.user_id = u.id and c.dish_id = 1

db.getCollection(‘Dish’).find({_id : 1})

Page 14: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Update

SQL NoSQL

UPDATE user SET nickname = ‘Bryan’ WHERE id=1 db.getCollection(‘User’).update({_id : 1}, {$set : {nickname : ‘Bryan’}})

{name: “White Rice”

ingredients : [“rice”, “garlic”],

comments : Array[

{

text : ‘This rice is really good’

user : {

nickname : ‘FoodLover’,

email: ‘[email protected]

}

]

Data Inconsistency

Page 15: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Delete

SQL NoSQL

DELETE FROM ingredient WHERE dish_id=1

DELETE FROM comment WHERE dish_id=1

DELETE FROM dish WHERE id=1

db.getCollection(‘Dish’).remove({_id : 1})

Page 16: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Java MongoDB Driver

Page 17: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Where is theFramework to

Map Java Objectsand Documents?

Spring Data

Page 18: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Spring Data

“This is an umbrella project which contains many subprojects that are specific to a given database”

• MongoDB

• Neo4j

• Cassandra

• JDBC Extensions

• Redis

• Etc

Page 19: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

How do we get started?

• Add this maven configuration to the pom.xml file

• Add the MongoDB config properties to the config file

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>1.10.6.RELEASE</version></dependency>

spring.data.mongodb.host=localhostspring.data.mongodb.port=27017spring.data.mongodb.database=dish-db

Page 20: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Application Layers

Page 21: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

DishController DishService DishMongoRepository

Application Layers

Page 22: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

How to create MongoDB Repository?

package com.fmodos.dish.infraestructure.mongodb;

import org.springframework.data.mongodb.repository.MongoRepository;import com.fmodos.dish.domain.Dish;

public interface DishMongoRepository extends MongoRepository<Dish, String> {

}

Page 23: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

How to use the MongoDB Repository?

@Servicepublic class DishService {

@AutowiredDishMongoRepository dishRepository;

public void insert(Dish dish) {dishRepository.insert(dish);

}

public interface DishMongoRepository extends MongoRepository<Dish, String> {

}

Where is the insertmethod?

Page 24: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

SpringData Repositories

MongoRepository

PagingAndSortingRepository

CrudRepository

Repository

DishMongoRepository

<extends>

Page 25: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

SpringData Repositories

<S extends T> S save(S entity);

<S extends T> Iterable<S> save(Iterable<S> entities);

long count();

void delete(ID id);

void delete(T entity);

void delete(Iterable<? extends T> entities);

void deleteAll();

dishMongoRepository.delete("id");

List<Dish> listDish = new ArrayList<Dish>();List<Dish> savedList = dishMongoRepository.save(listDish);

long count = dishMongoRepository.count();

Page 26: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

SpringData Repositories

T findOne(ID id);

boolean exists(ID id);

Iterable<T> findAll();

Iterable<T> findAll(Iterable<ID> ids);

Iterable<T> findAll(Sort sort);

Page<T> findAll(Pageable pageable);

List<Dish> listDish = dishRepository.findAll()

Dish dish = dishRepository.findOne(id)

Page<Dish> pageDish = dishMongoRepository.findAll(new PageRequest(1, 10));

Page 27: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

What about Query Filter?

public interface DishMongoRepository extends MongoRepository<Dish, String> {

public List<Dish> findByName(String name);

public List<Dish> findByNameAndDateCreatedGreaterThan(String name Date dateCreated);

}

“Methods should have verb or verb phrase names” Clean Code

Page 28: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

What is the magic? DSL – Dynamic Reception

• Handle messages without defining them in the receiving class

• Build dynamic queries using the method declaration

Page 29: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Spring Data Query

Keyword Sample Logical result

After findByBirthdateAfter(Date date) {"birthdate" : {"$gt" : date}}

GreaterThan findByAgeGreaterThan(int age) {"age" : {"$gt" : age}}

GreaterThanEqual findByAgeGreaterThanEqual(int

age)

{"age" : {"$gte" : age}}

Before findByBirthdateBefore(Date date) {"birthdate" : {"$lt" : date}}

LessThan findByAgeLessThan(int age) {"age" : {"$lt" : age}}

LessThanEqual findByAgeLessThanEqual(int age) {"age" : {"$lte" : age}}

Between findByAgeBetween(int from, int to) {"age" : {"$gt" : from, "$lt" : to}}

In findByAgeIn(Collection ages) {"age" : {"$in" : [ages…]}}

NotIn findByAgeNotIn(Collection ages) {"age" : {"$nin" : [ages…]}}

IsNotNull, NotNull findByFirstnameNotNull() {"firstname" : {"$ne" : null}}

IsNull, Null findByFirstnameNull() {"firstname" : null}

Like, StartingWith, EndingWith findByFirstnameLike(String name) {"firstname" : name} (name as

regex)

NotLike, IsNotLike findByFirstnameNotLike(String

name)

{"firstname" : { "$not" : name }}

(name as regex)

Page 30: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Spring Data Query

Containing on String findByFirstnameContaining(String

name)

{"firstname" : name} (name as regex)

NotContaining on String findByFirstnameNotContaining(String

name)

{"firstname" : { "$not" : name}} (name

as regex)

Containing on Collection findByAddressesContaining(Address

address)

{"addresses" : { "$in" : address}}

NotContaining on Collection findByAddressesNotContaining(Addr

ess address)

{"addresses" : { "$not" : { "$in" :

address}}}

Regex findByFirstnameRegex(String

firstname)

{"firstname" : {"$regex" : firstname }}

(No keyword) findByFirstname(String name) {"firstname" : name}

Not findByFirstnameNot(String name) {"firstname" : {"$ne" : name}}

IsTrue, True findByActiveIsTrue() {"active" : true}

IsFalse, False findByActiveIsFalse() {"active" : false}

Exists findByLocationExists(boolean exists) {"location" : {"$exists" : exists }}

Page 31: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

MongoDB JSON Based Query

public interface DishMongoRepository extends MongoRepository<Dish, String> {

@Query(value="{ 'ingredients' : {$in : ?0 }", fields="{ 'name' : 1}")public List<Dish> findNameByIngredients(List<String> ingredients);

}

Page 32: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

MongoTemplate Operations

mongoTemplate.upsert(new Query(Criteria.where("name").is("Brazil Food")), Update.update("description", "Really Good Food"), Dish.class)

@AutowiredMongoTemplate mongoTemplate;

• Upsert - Update or insert a new Document combining the Query and the Update values

• Autowire MongoTemplate

• FindAndModify – Query the Document, update it and return the Updated one

Dish dish = mongoTemplate.findAndModify(newQuery(Criteria.where("name").is("Brazil Food")), Update.update("description", "Really Good Food"), Dish.class);

“The design goal was to make it as easy as possible totransition between the use of the base MongoDB driver andMongoOperations”

Page 33: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

How to combine Repository and MongoTemplate?

interfaceDishMongoRepository

interfaceMongoRepository

interfaceIDishMongoTemplateRepository

classDishMongoTemplateRepository

extends

extends

extends

Page 34: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

DishController DishService DishMongoRepository

Application Layers

High Coupling Between DishService Businesse Rules andMongoDB

Page 35: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Application Layers

DishController DishService IDishRepository

MongoDishRepository

JpaRepository

<extends>

<extends>

SQLDishRepository

<extends>

Page 36: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Database Resilience – Circuit Breaker

IDishRepository

MongoDishRepository

SQLDishRepository

HystrixRepository

<extends>

Page 37: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

DemoLessons Learned

Page 38: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Application

Query without IndexQuery without Projection

Page 39: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Cool features I never usedin Production

Page 40: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Full Text Query

Query query = TextQuery.queryText(new TextCriteria().matching("rice"));mongoTemplate.find(query, Dish.class);

Query in the Dish Fields annotated with @TextIndexed(weight=1)

Similar behavior would be to query using OR operator

Page 41: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

GeoSpatial – Query Player within Box

Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));List<Player> venues =

template.find(new Query(Criteria.where("location").withinBox(box)), Player.class);

class Player {private double[] location;

}

Page 42: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

GeoSpatial – Query by distance

Point location = new Point(-73.99171, 40.738868);NearQuery query = NearQuery.near(location).maxDistance(new Distance(10, Metrics.MILES));

GeoResults<SinglePerson> = operations.geoNear(query, SinglePerson.class);

Page 43: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Summary

• Document Oriented Modelling

• Native CRUD operations in MongoDB

• Application Layers

• SpringData Repositories

• SpringData Query

• MongoTemplate Operations

• Lessons Learned in Production

• FullTextQuery

• GeoSpatialQuery

Page 44: Deep Dive into Spring Data and MongoDB - Percona · 2019-06-03 · Map Java Objects and Documents? Spring Data. Spring Data ^This is an umbrella project which contains many subprojects

Thank you!@fmodos