SlideShare ist ein Scribd-Unternehmen logo
1 von 58
Downloaden Sie, um offline zu lesen
Multi-criteria Queries on a Cassandra Application
Jérôme Mainaud
Ippon Technologies © 2015#CassandraSummit
Who am I
Jérôme Mainaud
➔ @jxerome
➔ Software Architect at Ippon Technologies, Paris
➔ DataStax Solution Architect Certified
Ippon Technologies © 2015#CassandraSummit
Ippon Technologies
● 200 software engineers in France and the US
➔ Paris, Nantes, Bordeaux
➔ Richmond (Virginia), Washington (DC)
● Expertise
➔ Digital, Big Data and Cloud
➔ Java & Agile
● Open-source Projects :
➔ JHipster,
➔ Tatami …
● @ipponusa
Agenda
1. Context
2. Technical Stack
3. Modelisation
4. Implementation
5. Results
Ippon Technologies © 2015
Warning
The following slideshow features data patterns and
code performed by professionals.
Accordingly, Ippon and conference organisers must
insist that no one attempt to recreate any data pattern
and code performed in this slideshow.
Once Upon a time an app …
Ippon Technologies © 2015#CassandraSummit
Once Upon a time an app …
Invoice application in SAAS
➔ A single database for all users
➔ Data isolation for each user
High volume data
➔ 1 year
➔ 500 millions invoices
➔ 2 billions invoice lines
Ippon Technologies © 2015#CassandraSummit
Once Upon a time an app …
Ippon Technologies © 2015#CassandraSummit
Once Upon a time an app …
Ippon Technologies © 2015#CassandraSummit
Back-end evolution
Technical Stack
Ippon Technologies © 2015#CassandraSummit
Technical Stack
JHipster
➔ Spring Boot + AngularJS Application Generator
➔ Support JPA, MongoDB
➔ and now Cassandra!
Made us generate first version very fast
➔ Application skeleton ready in 5 minutes
➔ Add entities tables, objets and mapping
➔ Configuration, build, logs management, etc.
➔ Gatling Tests ready to use
http://jhipster.github.io
Ippon Technologies © 2015#CassandraSummit
Technical Stack
Spring Boot
➔ Build on Spring
➔ Convention over configuration
➔ Many “starters” ready to use
Services Web
➔ CXF instead of Spring MVC REST
Cassandra
➔ DataStax Enterprise
Java 8
Ippon Technologies © 2015#CassandraSummit
JHipster — Code generator
● But
➔ Cassandra was not yet supported
➔ No AngularJS nor frontend
➔ CXF instead of Spring MVC
Ippon Technologies © 2015#CassandraSummit
JHipster — Code generator
● But
➔ Cassandra was not yet supported
➔ No AngularJS nor frontend
➔ CXF instead of Spring MVC
● JHipster alpha generator
➔ Secret Generator secret used to
validate concepts before writing
Yeoman generator
Ippon Technologies © 2015#CassandraSummit
JHipster — Code generator
Julien Dubois
Code Generator
Ippon Technologies © 2015#CassandraSummit
Cassandra Driver Configuration
Spring Boot Configuration
➔ No integration of driver DataStax Java Driver in Spring Boot
➔ Created Spring Boot autoconfiguration of DataStax Java Driver
➔ Use the standard YAML File
Offered to Spring Boot 1.3
➔ Github ticket #2064 « Add a spring-boot-starter-data-cassandra »
➔ Still opened
Improved by the Community
➔ JHipster version was improved by pull-request
➔ Authentication, Load-Balancer config
Data Model
Ippon Technologies © 2015#CassandraSummit
Conceptual Model
Ippon Technologies © 2015#CassandraSummit
Physical Model
Ippon Technologies © 2015#CassandraSummit
create table invoice (
invoice_id timeuuid,
user_id uuid static,
firstname text static,
lastname text static,
invoice_date timestamp static,
payment_date timestamp static,
total_amount decimal static,
delivery_address text static,
delivery_city text static,
delivery_zipcode text static,
item_id timeuuid,
item_label text,
item_price decimal,
item_qty int,
item_total decimal,
primary key (invoice_id, item_id)
);
Table
Multi-criteria Search
Ippon Technologies © 2015#CassandraSummit
Multi-criteria Search
Mandatory Criteria
➔ User (implicit)
➔ Invoice date (range of dates)
Additional Criteria
➔ Client lastname
➔ Client firstname
➔ City
➔ Zipcode
Paginated Result
Ippon Technologies © 2015#CassandraSummit
Shall we use Solr ?
Ippon Technologies © 2015#CassandraSummit
Shall we use Solr ?
● Integrated in DataStax Enterprise
● Atomic and Automatic Index update
● Full-Text Search
Ippon Technologies © 2015#CassandraSummit
Shall we use Solr ?
● We search on static columns
➔ Solr don’t support them
● We search partitions
➔ Solr search lines
Ippon Technologies © 2015#CassandraSummit
Shall we use Solr ?
● We search on static columns
➔ Solr don’t support them
● We search partitions
➔ Solr search lines
Ippon Technologies © 2015#CassandraSummit
Shall we use secondary indexes ?
● Only one index used for a query
● Hard to get good performance with them
Ippon Technologies © 2015#CassandraSummit
Index Table
Use index tables
➔ Partition Key : Mandatory criteria and one additional criterium
○ user_id
○ invoice day (truncated invoice date)
○ additional criterium
➔ Clustering columns : Invoice UUID
Ippon Technologies © 2015#CassandraSummit
Index Table
Ippon Technologies © 2015#CassandraSummit
Materialized view
CREATE MATERIALIZED VIEW invoice_by_firstname
AS
SELECT invoice_id
FROM invoice
WHERE firstname IS NOT NULL
PRIMARY KEY ((user_id, invoice_day, firstname), invoice_id)
WITH CLUSTERING ORDER BY (invoice_id DESC)
new in
3.0
Ippon Technologies © 2015#CassandraSummit
Parallel Search on indexes
in memory
merge by application
Ippon Technologies © 2015#CassandraSummit
Parallel item detail queries
Result Page (id)
Ippon Technologies © 2015#CassandraSummit
Search
Search on date range
➔ loop an every days in the range and stop
when there is enough result for a page
Ippon Technologies © 2015#CassandraSummit
Search Complexity
Query count
➔ For each day in date range
○ 1 query per additional criterium filled (partition by query)
➔ 1 query per item in result page (partition by query)
Search Complexity
➔ partitions by query
Example: 3 criteria, 7 days, 100 items per page
➔ query count ≤ 3 × 7 + 100 = 121
JAVA
Indexes
Ippon Technologies © 2015#CassandraSummit
Index — Instances
@Repository
public class InvoiceByLastNameRepository extends IndexRepository<String> {
public InvoiceByLastNameRepository() {
super("invoice_by_lastname", "lastname", Invoice::getLastName, Criteria::getLastName);
}
}
@Repository
public class InvoiceByFirstNameRepository extends IndexRepository<String> {
public InvoiceByFirstNameRepository() {
super("invoice_by_firstname", "firstname", Invoice::getFirstName, Criteria::getFirstName);
}
}
Ippon Technologies © 2015#CassandraSummit
Index — Parent Class
public class IndexRepository<T> {
@Inject
private Session session;
private final String tableName;
private final String valueName;
private final Function<Invoice, T> valueGetter;
private final Function<Criteria, T> criteriumGetter;
private PreparedStatement insertStmt;
private PreparedStatement findStmt;
private PreparedStatement findWithOffsetStmt;
@PostConstruct
public void init() { /* initialize PreparedStatements */ }
Ippon Technologies © 2015#CassandraSummit
Index — Insert
@Override
public void insert(Invoice invoice) {
T value = valueGetter.apply(invoice);
if (value != null) {
session.execute(
insertStmt.bind(
invoice.getUserId(),
Dates.toDate(invoice.getInvoiceDay()),
value,
invoice.getId()));
}
}
Ippon Technologies © 2015#CassandraSummit
Index — Insert — Prepare Statement
insertStmt = session.prepare(
QueryBuilder.insertInto(tableName)
.value("user_id", bindMarker())
.value("invoice_day", bindMarker())
.value(valueName, bindMarker())
.value("invoice_id", bindMarker())
);
Ippon Technologies © 2015#CassandraSummit
Index — Insert — Date conversion
public static Date toDate(LocalDate date) {
return date == null ? null :
Date.from(date.atStartOfDay().atZone(ZoneOffset.systemDefault()).toInstant());
}
Ippon Technologies © 2015#CassandraSummit
Index — Search
@Override
public CompletableFuture<Iterator<UUID>> find(Criteria criteria, LocalDate day, UUID offset) {
T criterium = criteriumGetter.apply(criteria);
if (criterium == null) {
return CompletableFuture.completedFuture(null);
}
BoundStatement stmt;
if (invoiceIdOffset == null) {
stmt = findStmt.bind(criteria.getUserId(), Dates.toDate(day), criterium);
} else {
stmt = findWithOffsetStmt.bind(criteria.getUserId(), Dates.toDate(day), criterium, offset);
}
return Jdk8.completableFuture(session.executeAsync(stmt))
.thenApply(rs -> Iterators.transform(rs.iterator(), row -> row.getUUID(0)));
}
Ippon Technologies © 2015#CassandraSummit
Index — Search — Prepare Statement
findWithOffsetStmt = session.prepare(
QueryBuilder.select()
.column("invoice_id")
.from(tableName)
.where(eq("user_id", bindMarker()))
.and(eq("invoice_day", bindMarker()))
.and(eq(valueName, bindMarker()))
.and(lte("invoice_id", bindMarker()))
);
Ippon Technologies © 2015#CassandraSummit
Index — Search (Guava to Java 8)
public static <T> CompletableFuture<T> completableFuture(ListenableFuture<T> guavaFuture) {
CompletableFuture<T> future = new CompletableFuture<>();
Futures.addCallback(guavaFuture, new FutureCallback<T>() {
@Override
public void onSuccess(T result) {
future.complete(result);
}
@Override
public void onFailure(Throwable t) {
future.completeExceptionally(t);
}
});
return future;
}
JAVA
Search Service
Ippon Technologies © 2015#CassandraSummit
Service — Class
@Service
public class InvoiceSearchService {
@Inject
private InvoiceRepository invoiceRepository;
@Inject
private InvoiceByDayRepository byDayRepository;
@Inject
private InvoiceByLastNameRepository byLastNameRepository;
@Inject
private InvoiceByFirstNameRepository byLastNameRepository;
@Inject
private InvoiceByCityRepository byCityRepository;
@Inject
private InvoiceByZipCodeRepository byZipCodeRepository;
Ippon Technologies © 2015#CassandraSummit
Service — Search
public ResultPage findByCriteria(Criteria criteria) {
return byDateInteval(criteria, (crit, day, offset) -> {
CompletableFuture<Iterator<UUID>> futureUuidIt;
if (crit.hasIndexedCriteria()) {
/*
* ... Doing multi-criteria search; see next slide ...
*/
} else {
futureUuidIt = byDayRepository.find(crit.getUserId(), day, offset);
}
return futureUuidIt;
});
}
Ippon Technologies © 2015#CassandraSummit
Service — Search
CompletableFuture<Iterator<UUID>>[] futures = Stream.<IndexRepository> of(
byLastNameRepository, byFirstNameRepository, byCityRepository, byZipCodeRepository)
.map(repo -> repo.find(crit, day, offset))
.toArray(CompletableFuture[]::new);
futureUuidIt = CompletableFuture.allOf(futures).thenApply(v ->
Iterators.intersection(TimeUUIDComparator.desc,
Stream.of(futures)
.map(CompletableFuture::join)
.filter(Objects::nonNull)
.collect(Collectors.toList())));
Ippon Technologies © 2015#CassandraSummit
Service — UUIDs Comparator
/**
* TimeUUID Comparator equivalent to Cassandra’s Comparator:
* @see org.apache.cassandra.db.marshal.TimeUUIDType#compare()
*/
public enum TimeUUIDComparator implements Comparator<UUID> {
desc {
@Override
public int compare(UUID o1, UUID o2) {
long delta = o2.timestamp() - o1.timestamp();
if (delta != 0)
return Ints.saturatedCast(delta);
return o2.compareTo(o1);
}
};
}
Ippon Technologies © 2015#CassandraSummit
Service — Days Loop
@FunctionalInterface
private static interface DayQuery {
CompletableFuture<Iterator<UUID>> find(Criteria criteria, LocalDate day, UUID invoiceIdOffset);
}
private ResultPage byDateInteval(Criteria criteria, DayQuery dayQuery) {
int limit = criteria.getLimit();
List<Invoice> resultList = new ArrayList<>(limit);
LocalDate dayOffset = criteria.getDayOffset();
UUID invoiceIdOffset = criteria.getInvoiceIdOffset();
/* ... Loop on days ; to be seen in next slide ... */
return new ResultPage(resultList);
}
Ippon Technologies © 2015#CassandraSummit
Service — Days Loop
LocalDate day = criteria.getLastDay();
do {
Iterator<UUID> uuidIt = dayQuery.find(criteria, day, invoiceIdOffset).join();
limit -= loadInvoices(resultList, uuidIt, criteria, limit);
if (uuidIt.hasNext()) {
return new ResultPage(resultList, day, uuidIt.next());
}
day = day.minusDays(1);
invoiceIdOffset = null;
} while (!day.isBefore(criteria.getFirstDay()));
Ippon Technologies © 2015#CassandraSummit
Service — Invoices Loading
private int loadInvoices(List<Invoice> resultList, Iterator<UUID> uuidIt, int limit) {
List<CompletableFuture<Invoice>> futureList = new ArrayList<>(limit);
for (int i = 0; i < limit && uuidIt.hasNext(); ++i) {
futureList.add(invoiceRepository.findOne(uuidIt.next()));
}
futureList.stream()
.map(CompletableFuture::join)
.forEach(resultList::add);
return futureList.size();
}
Results
Ippon Technologies © 2015#CassandraSummit
Limits
● We got an exact-match search
➔ No full text search
➔ No « start with » search
➔ No pattern base search
● Requires highly discriminating mandatory criteria
➔ user_id & invoice_day
● Pagination doesn’t give total item count
➔ Could be done with additionnal query cost
● No sort availaible
Ippon Technologies © 2015#CassandraSummit
Hardware
● Hosted by Ippon Hosting
● 8 nodes
➔ 16 Gb RAM
➔ Two SSD drives with 256 Gb in RAID 0
● 6 nodes dedicated to Cassandra cluster
● 2 nodes dedicated to the application
Ippon Technologies © 2015#CassandraSummit
Application
● 5,000 concurrent users
● 9 months of data loaded
➔ Legacy system: store 1 year; search on last 3 months.
➔ Target: 3 years of history
● Real-time search Result
➔ Data are immediately available
➔ Legacy system: data available next day
● Cost Killer
Q & A
PARIS
BORDEAUX
NANTES
WASHINGTON
NEW-YORK
RICHMOND
contact@ippon.fr
www.ippon.fr - www.ippon-hosting.com - www.ippon-digital.fr
@ippontech
-
01 46 12 48 48

Weitere ähnliche Inhalte

Was ist angesagt?

Embrace Change - Embrace OSGi
Embrace Change - Embrace OSGiEmbrace Change - Embrace OSGi
Embrace Change - Embrace OSGiCarsten Ziegeler
 
Preparing your code for Java 9
Preparing your code for Java 9Preparing your code for Java 9
Preparing your code for Java 9Deepu Xavier
 
JPQL/ JPA Activity 1
JPQL/ JPA Activity 1JPQL/ JPA Activity 1
JPQL/ JPA Activity 1SFI
 
Running Spring Boot Applications as GraalVM Native Images
Running Spring Boot Applications as GraalVM Native ImagesRunning Spring Boot Applications as GraalVM Native Images
Running Spring Boot Applications as GraalVM Native ImagesVMware Tanzu
 
BP207 - Meet the Java Application Server You Already Own – IBM Domino
BP207 - Meet the Java Application Server You Already Own – IBM DominoBP207 - Meet the Java Application Server You Already Own – IBM Domino
BP207 - Meet the Java Application Server You Already Own – IBM DominoSerdar Basegmez
 
An Introduction to Maven Part 1
An Introduction to Maven Part 1An Introduction to Maven Part 1
An Introduction to Maven Part 1MD Sayem Ahmed
 
Spring Native and Spring AOT
Spring Native and Spring AOTSpring Native and Spring AOT
Spring Native and Spring AOTVMware Tanzu
 
Modern web application development with java ee 7
Modern web application development with java ee 7Modern web application development with java ee 7
Modern web application development with java ee 7Shekhar Gulati
 
Virgo Project Creation Review
Virgo Project Creation ReviewVirgo Project Creation Review
Virgo Project Creation Reviewglynnormington
 
SpringOne Platform recap 정윤진
SpringOne Platform recap 정윤진SpringOne Platform recap 정윤진
SpringOne Platform recap 정윤진VMware Tanzu Korea
 
Geneva Jug (30th March, 2010) - Maven
Geneva Jug (30th March, 2010) - MavenGeneva Jug (30th March, 2010) - Maven
Geneva Jug (30th March, 2010) - MavenArnaud Héritier
 
Alpes Jug (29th March, 2010) - Apache Maven
Alpes Jug (29th March, 2010) - Apache MavenAlpes Jug (29th March, 2010) - Apache Maven
Alpes Jug (29th March, 2010) - Apache MavenArnaud Héritier
 
The 2014 Decision Makers Guide to Java Web Frameworks
The 2014 Decision Makers Guide to Java Web FrameworksThe 2014 Decision Makers Guide to Java Web Frameworks
The 2014 Decision Makers Guide to Java Web FrameworksKunal Ashar
 
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...Nuxeo
 

Was ist angesagt? (19)

Embrace Change - Embrace OSGi
Embrace Change - Embrace OSGiEmbrace Change - Embrace OSGi
Embrace Change - Embrace OSGi
 
Maven
MavenMaven
Maven
 
FreshAir2008
FreshAir2008FreshAir2008
FreshAir2008
 
Preparing your code for Java 9
Preparing your code for Java 9Preparing your code for Java 9
Preparing your code for Java 9
 
JPQL/ JPA Activity 1
JPQL/ JPA Activity 1JPQL/ JPA Activity 1
JPQL/ JPA Activity 1
 
Running Spring Boot Applications as GraalVM Native Images
Running Spring Boot Applications as GraalVM Native ImagesRunning Spring Boot Applications as GraalVM Native Images
Running Spring Boot Applications as GraalVM Native Images
 
BP207 - Meet the Java Application Server You Already Own – IBM Domino
BP207 - Meet the Java Application Server You Already Own – IBM DominoBP207 - Meet the Java Application Server You Already Own – IBM Domino
BP207 - Meet the Java Application Server You Already Own – IBM Domino
 
An Introduction to Maven Part 1
An Introduction to Maven Part 1An Introduction to Maven Part 1
An Introduction to Maven Part 1
 
Intro To OSGi
Intro To OSGiIntro To OSGi
Intro To OSGi
 
JVMs in Containers
JVMs in ContainersJVMs in Containers
JVMs in Containers
 
Spring Native and Spring AOT
Spring Native and Spring AOTSpring Native and Spring AOT
Spring Native and Spring AOT
 
Modern web application development with java ee 7
Modern web application development with java ee 7Modern web application development with java ee 7
Modern web application development with java ee 7
 
Virgo Project Creation Review
Virgo Project Creation ReviewVirgo Project Creation Review
Virgo Project Creation Review
 
SpringOne Platform recap 정윤진
SpringOne Platform recap 정윤진SpringOne Platform recap 정윤진
SpringOne Platform recap 정윤진
 
Geneva Jug (30th March, 2010) - Maven
Geneva Jug (30th March, 2010) - MavenGeneva Jug (30th March, 2010) - Maven
Geneva Jug (30th March, 2010) - Maven
 
Alpes Jug (29th March, 2010) - Apache Maven
Alpes Jug (29th March, 2010) - Apache MavenAlpes Jug (29th March, 2010) - Apache Maven
Alpes Jug (29th March, 2010) - Apache Maven
 
The 2014 Decision Makers Guide to Java Web Frameworks
The 2014 Decision Makers Guide to Java Web FrameworksThe 2014 Decision Makers Guide to Java Web Frameworks
The 2014 Decision Makers Guide to Java Web Frameworks
 
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...
Creating Large Scale Software Platforms with OSGi and an Extension Point Mode...
 
Karaf ee-apachecon eu-2012
Karaf ee-apachecon eu-2012Karaf ee-apachecon eu-2012
Karaf ee-apachecon eu-2012
 

Andere mochten auch

Quoi de neuf pour JHipster en 2016
Quoi de neuf pour JHipster en 2016Quoi de neuf pour JHipster en 2016
Quoi de neuf pour JHipster en 2016Ippon
 
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...Ippon
 
Démystifions le machine learning avec spark par David Martin pour le Salon B...
Démystifions le machine learning avec spark par David Martin pour le Salon B...Démystifions le machine learning avec spark par David Martin pour le Salon B...
Démystifions le machine learning avec spark par David Martin pour le Salon B...Ippon
 
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014Ippon
 
Cassandra Java Driver : vers Cassandra 1.2 et au-delà
Cassandra Java Driver : vers Cassandra 1.2 et au-delàCassandra Java Driver : vers Cassandra 1.2 et au-delà
Cassandra Java Driver : vers Cassandra 1.2 et au-delàIppon
 
Agilité, n’oublions pas les valeurs
Agilité, n’oublions pas les valeursAgilité, n’oublions pas les valeurs
Agilité, n’oublions pas les valeursIppon
 
Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Ippon
 
Atelier TDD (Test Driven Development)
Atelier TDD (Test Driven Development)Atelier TDD (Test Driven Development)
Atelier TDD (Test Driven Development)Ippon
 
Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Ippon
 
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014Ippon
 
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014Web API & Cache, the HTTP way - Ippevent 10 Juin 2014
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014Ippon
 
Formation Usine Logicielle gratuite par Ippon 2014
Formation Usine Logicielle gratuite par Ippon 2014Formation Usine Logicielle gratuite par Ippon 2014
Formation Usine Logicielle gratuite par Ippon 2014Ippon
 
Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Ippon
 
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Ippon
 
Formation GIT gratuite par ippon 2014
Formation GIT gratuite par ippon 2014Formation GIT gratuite par ippon 2014
Formation GIT gratuite par ippon 2014Ippon
 
JPA avec Cassandra, grâce à Achilles
JPA avec Cassandra, grâce à AchillesJPA avec Cassandra, grâce à Achilles
JPA avec Cassandra, grâce à AchillesIppon
 
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileNouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileIppon
 
Ippon: Doing multi-criteria queries on a Cassandra application (Français)
Ippon: Doing multi-criteria queries on a Cassandra application (Français)Ippon: Doing multi-criteria queries on a Cassandra application (Français)
Ippon: Doing multi-criteria queries on a Cassandra application (Français)DataStax Academy
 
La gouvernance de l'information est une affaire de changement - Conférence SE...
La gouvernance de l'information est une affaire de changement - Conférence SE...La gouvernance de l'information est une affaire de changement - Conférence SE...
La gouvernance de l'information est une affaire de changement - Conférence SE...Perrein Jean-Pascal
 
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...Perrein Jean-Pascal
 

Andere mochten auch (20)

Quoi de neuf pour JHipster en 2016
Quoi de neuf pour JHipster en 2016Quoi de neuf pour JHipster en 2016
Quoi de neuf pour JHipster en 2016
 
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...
Système d’Information à l’Apec : un nouveau coeur de métier mis en place avec...
 
Démystifions le machine learning avec spark par David Martin pour le Salon B...
Démystifions le machine learning avec spark par David Martin pour le Salon B...Démystifions le machine learning avec spark par David Martin pour le Salon B...
Démystifions le machine learning avec spark par David Martin pour le Salon B...
 
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014
One Web (API?) – Alexandre Bertails - Ippevent 10 juin 2014
 
Cassandra Java Driver : vers Cassandra 1.2 et au-delà
Cassandra Java Driver : vers Cassandra 1.2 et au-delàCassandra Java Driver : vers Cassandra 1.2 et au-delà
Cassandra Java Driver : vers Cassandra 1.2 et au-delà
 
Agilité, n’oublions pas les valeurs
Agilité, n’oublions pas les valeursAgilité, n’oublions pas les valeurs
Agilité, n’oublions pas les valeurs
 
Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014
 
Atelier TDD (Test Driven Development)
Atelier TDD (Test Driven Development)Atelier TDD (Test Driven Development)
Atelier TDD (Test Driven Development)
 
Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon
 
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014
Realtime Web avec Akka, Kafka, Spark et Mesos - Devoxx Paris 2014
 
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014Web API & Cache, the HTTP way - Ippevent 10 Juin 2014
Web API & Cache, the HTTP way - Ippevent 10 Juin 2014
 
Formation Usine Logicielle gratuite par Ippon 2014
Formation Usine Logicielle gratuite par Ippon 2014Formation Usine Logicielle gratuite par Ippon 2014
Formation Usine Logicielle gratuite par Ippon 2014
 
Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014Formation html5 CSS3 offerte par ippon 2014
Formation html5 CSS3 offerte par ippon 2014
 
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
 
Formation GIT gratuite par ippon 2014
Formation GIT gratuite par ippon 2014Formation GIT gratuite par ippon 2014
Formation GIT gratuite par ippon 2014
 
JPA avec Cassandra, grâce à Achilles
JPA avec Cassandra, grâce à AchillesJPA avec Cassandra, grâce à Achilles
JPA avec Cassandra, grâce à Achilles
 
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et MobileNouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
Nouveau look pour une nouvelle vie : HTML5, Spring, NoSQL et Mobile
 
Ippon: Doing multi-criteria queries on a Cassandra application (Français)
Ippon: Doing multi-criteria queries on a Cassandra application (Français)Ippon: Doing multi-criteria queries on a Cassandra application (Français)
Ippon: Doing multi-criteria queries on a Cassandra application (Français)
 
La gouvernance de l'information est une affaire de changement - Conférence SE...
La gouvernance de l'information est une affaire de changement - Conférence SE...La gouvernance de l'information est une affaire de changement - Conférence SE...
La gouvernance de l'information est une affaire de changement - Conférence SE...
 
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...
Offre 3org Conseil sur la gouvernance et la gestion de l'information d'entrep...
 

Ähnlich wie Multi criteria queries on a cassandra application

Cloud-native Patterns
Cloud-native PatternsCloud-native Patterns
Cloud-native PatternsVMware Tanzu
 
Cloud-native Patterns (July 4th, 2019)
Cloud-native Patterns (July 4th, 2019)Cloud-native Patterns (July 4th, 2019)
Cloud-native Patterns (July 4th, 2019)Alexandre Roman
 
P4 Introduction
P4 Introduction P4 Introduction
P4 Introduction Netronome
 
Webinar - Building Custom Extensions With AppDynamics
Webinar - Building Custom Extensions With AppDynamicsWebinar - Building Custom Extensions With AppDynamics
Webinar - Building Custom Extensions With AppDynamicsTodd Radel
 
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...Khai Tran
 
Taking AppSec to 11 - BSides Austin 2016
Taking AppSec to 11 - BSides Austin 2016Taking AppSec to 11 - BSides Austin 2016
Taking AppSec to 11 - BSides Austin 2016Matt Tesauro
 
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...Dataconomy Media
 
How to Architect and Develop Cloud Native Applications
How to Architect and Develop Cloud Native ApplicationsHow to Architect and Develop Cloud Native Applications
How to Architect and Develop Cloud Native ApplicationsSufyaan Kazi
 
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things Better
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things BetterTaking AppSec to 11: AppSec Pipeline, DevOps and Making Things Better
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things BetterMatt Tesauro
 
To be or not to be serverless
To be or not to be serverlessTo be or not to be serverless
To be or not to be serverlessSteve Houël
 
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...Overview and Walkthrough of the Application Programming Model with SAP Cloud ...
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...SAP Cloud Platform
 
Serverless survival kit
Serverless survival kitServerless survival kit
Serverless survival kitSteve Houël
 
Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Melania Andrisan (Danciu)
 
How Zalando integrates Kubernetes with AWS
How Zalando integrates Kubernetes with AWSHow Zalando integrates Kubernetes with AWS
How Zalando integrates Kubernetes with AWSUri Savelchev
 
Application Modernization with PKS / Kubernetes
Application Modernization with PKS / KubernetesApplication Modernization with PKS / Kubernetes
Application Modernization with PKS / KubernetesPaul Czarkowski
 

Ähnlich wie Multi criteria queries on a cassandra application (20)

Cloud-native Patterns
Cloud-native PatternsCloud-native Patterns
Cloud-native Patterns
 
Cloud-native Patterns (July 4th, 2019)
Cloud-native Patterns (July 4th, 2019)Cloud-native Patterns (July 4th, 2019)
Cloud-native Patterns (July 4th, 2019)
 
P4 Introduction
P4 Introduction P4 Introduction
P4 Introduction
 
Sst hackathon express
Sst hackathon expressSst hackathon express
Sst hackathon express
 
Webinar - Building Custom Extensions With AppDynamics
Webinar - Building Custom Extensions With AppDynamicsWebinar - Building Custom Extensions With AppDynamics
Webinar - Building Custom Extensions With AppDynamics
 
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...
Conquering the Lambda architecture in LinkedIn metrics platform with Apache C...
 
Machine Learning with Apache Spark
Machine Learning with Apache SparkMachine Learning with Apache Spark
Machine Learning with Apache Spark
 
Taking AppSec to 11 - BSides Austin 2016
Taking AppSec to 11 - BSides Austin 2016Taking AppSec to 11 - BSides Austin 2016
Taking AppSec to 11 - BSides Austin 2016
 
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...
Big Data Helsinki v 3 | "Distributed Machine and Deep Learning at Scale with ...
 
How to Architect and Develop Cloud Native Applications
How to Architect and Develop Cloud Native ApplicationsHow to Architect and Develop Cloud Native Applications
How to Architect and Develop Cloud Native Applications
 
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things Better
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things BetterTaking AppSec to 11: AppSec Pipeline, DevOps and Making Things Better
Taking AppSec to 11: AppSec Pipeline, DevOps and Making Things Better
 
To be or not to be serverless
To be or not to be serverlessTo be or not to be serverless
To be or not to be serverless
 
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...Overview and Walkthrough of the Application Programming Model with SAP Cloud ...
Overview and Walkthrough of the Application Programming Model with SAP Cloud ...
 
Microservices chassis
Microservices chassisMicroservices chassis
Microservices chassis
 
Serverless survival kit
Serverless survival kitServerless survival kit
Serverless survival kit
 
Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017Serverless Single Page Apps with React and Redux at ItCamp 2017
Serverless Single Page Apps with React and Redux at ItCamp 2017
 
Kraken.js Lab Primer
Kraken.js Lab PrimerKraken.js Lab Primer
Kraken.js Lab Primer
 
CI/CD using AWS developer tools
CI/CD using AWS developer toolsCI/CD using AWS developer tools
CI/CD using AWS developer tools
 
How Zalando integrates Kubernetes with AWS
How Zalando integrates Kubernetes with AWSHow Zalando integrates Kubernetes with AWS
How Zalando integrates Kubernetes with AWS
 
Application Modernization with PKS / Kubernetes
Application Modernization with PKS / KubernetesApplication Modernization with PKS / Kubernetes
Application Modernization with PKS / Kubernetes
 

Mehr von Ippon

Offre 2015 numeriq_ippon
Offre 2015 numeriq_ipponOffre 2015 numeriq_ippon
Offre 2015 numeriq_ipponIppon
 
CDI par la pratique
CDI par la pratiqueCDI par la pratique
CDI par la pratiqueIppon
 
Hibernate vs le_cloud_computing
Hibernate vs le_cloud_computingHibernate vs le_cloud_computing
Hibernate vs le_cloud_computingIppon
 
Stateful is beautiful
Stateful is beautifulStateful is beautiful
Stateful is beautifulIppon
 
Présentation Ippon DGA Liferay Symposium 2011
Présentation Ippon DGA Liferay Symposium 2011Présentation Ippon DGA Liferay Symposium 2011
Présentation Ippon DGA Liferay Symposium 2011Ippon
 
Scrum et forfait
Scrum et forfaitScrum et forfait
Scrum et forfaitIppon
 
Mule ESB Summit 2010 avec Ippon
Mule ESB Summit 2010 avec IpponMule ESB Summit 2010 avec Ippon
Mule ESB Summit 2010 avec IpponIppon
 
Présentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitPrésentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitIppon
 
Présentation Rex GWT 2.0
Présentation Rex GWT 2.0Présentation Rex GWT 2.0
Présentation Rex GWT 2.0Ippon
 
Presentation Rex Methodes Agiles
Presentation Rex Methodes AgilesPresentation Rex Methodes Agiles
Presentation Rex Methodes AgilesIppon
 
Seminaire Portail Open Source
Seminaire Portail Open SourceSeminaire Portail Open Source
Seminaire Portail Open SourceIppon
 

Mehr von Ippon (11)

Offre 2015 numeriq_ippon
Offre 2015 numeriq_ipponOffre 2015 numeriq_ippon
Offre 2015 numeriq_ippon
 
CDI par la pratique
CDI par la pratiqueCDI par la pratique
CDI par la pratique
 
Hibernate vs le_cloud_computing
Hibernate vs le_cloud_computingHibernate vs le_cloud_computing
Hibernate vs le_cloud_computing
 
Stateful is beautiful
Stateful is beautifulStateful is beautiful
Stateful is beautiful
 
Présentation Ippon DGA Liferay Symposium 2011
Présentation Ippon DGA Liferay Symposium 2011Présentation Ippon DGA Liferay Symposium 2011
Présentation Ippon DGA Liferay Symposium 2011
 
Scrum et forfait
Scrum et forfaitScrum et forfait
Scrum et forfait
 
Mule ESB Summit 2010 avec Ippon
Mule ESB Summit 2010 avec IpponMule ESB Summit 2010 avec Ippon
Mule ESB Summit 2010 avec Ippon
 
Présentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitPrésentation du retour d'expérience sur Git
Présentation du retour d'expérience sur Git
 
Présentation Rex GWT 2.0
Présentation Rex GWT 2.0Présentation Rex GWT 2.0
Présentation Rex GWT 2.0
 
Presentation Rex Methodes Agiles
Presentation Rex Methodes AgilesPresentation Rex Methodes Agiles
Presentation Rex Methodes Agiles
 
Seminaire Portail Open Source
Seminaire Portail Open SourceSeminaire Portail Open Source
Seminaire Portail Open Source
 

Kürzlich hochgeladen

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 

Kürzlich hochgeladen (20)

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 

Multi criteria queries on a cassandra application

  • 1. Multi-criteria Queries on a Cassandra Application Jérôme Mainaud
  • 2. Ippon Technologies © 2015#CassandraSummit Who am I Jérôme Mainaud ➔ @jxerome ➔ Software Architect at Ippon Technologies, Paris ➔ DataStax Solution Architect Certified
  • 3. Ippon Technologies © 2015#CassandraSummit Ippon Technologies ● 200 software engineers in France and the US ➔ Paris, Nantes, Bordeaux ➔ Richmond (Virginia), Washington (DC) ● Expertise ➔ Digital, Big Data and Cloud ➔ Java & Agile ● Open-source Projects : ➔ JHipster, ➔ Tatami … ● @ipponusa
  • 4. Agenda 1. Context 2. Technical Stack 3. Modelisation 4. Implementation 5. Results
  • 5. Ippon Technologies © 2015 Warning The following slideshow features data patterns and code performed by professionals. Accordingly, Ippon and conference organisers must insist that no one attempt to recreate any data pattern and code performed in this slideshow.
  • 6. Once Upon a time an app …
  • 7. Ippon Technologies © 2015#CassandraSummit Once Upon a time an app … Invoice application in SAAS ➔ A single database for all users ➔ Data isolation for each user High volume data ➔ 1 year ➔ 500 millions invoices ➔ 2 billions invoice lines
  • 8. Ippon Technologies © 2015#CassandraSummit Once Upon a time an app …
  • 9. Ippon Technologies © 2015#CassandraSummit Once Upon a time an app …
  • 10. Ippon Technologies © 2015#CassandraSummit Back-end evolution
  • 12. Ippon Technologies © 2015#CassandraSummit Technical Stack JHipster ➔ Spring Boot + AngularJS Application Generator ➔ Support JPA, MongoDB ➔ and now Cassandra! Made us generate first version very fast ➔ Application skeleton ready in 5 minutes ➔ Add entities tables, objets and mapping ➔ Configuration, build, logs management, etc. ➔ Gatling Tests ready to use http://jhipster.github.io
  • 13. Ippon Technologies © 2015#CassandraSummit Technical Stack Spring Boot ➔ Build on Spring ➔ Convention over configuration ➔ Many “starters” ready to use Services Web ➔ CXF instead of Spring MVC REST Cassandra ➔ DataStax Enterprise Java 8
  • 14. Ippon Technologies © 2015#CassandraSummit JHipster — Code generator ● But ➔ Cassandra was not yet supported ➔ No AngularJS nor frontend ➔ CXF instead of Spring MVC
  • 15. Ippon Technologies © 2015#CassandraSummit JHipster — Code generator ● But ➔ Cassandra was not yet supported ➔ No AngularJS nor frontend ➔ CXF instead of Spring MVC ● JHipster alpha generator ➔ Secret Generator secret used to validate concepts before writing Yeoman generator
  • 16. Ippon Technologies © 2015#CassandraSummit JHipster — Code generator Julien Dubois Code Generator
  • 17. Ippon Technologies © 2015#CassandraSummit Cassandra Driver Configuration Spring Boot Configuration ➔ No integration of driver DataStax Java Driver in Spring Boot ➔ Created Spring Boot autoconfiguration of DataStax Java Driver ➔ Use the standard YAML File Offered to Spring Boot 1.3 ➔ Github ticket #2064 « Add a spring-boot-starter-data-cassandra » ➔ Still opened Improved by the Community ➔ JHipster version was improved by pull-request ➔ Authentication, Load-Balancer config
  • 19. Ippon Technologies © 2015#CassandraSummit Conceptual Model
  • 20. Ippon Technologies © 2015#CassandraSummit Physical Model
  • 21. Ippon Technologies © 2015#CassandraSummit create table invoice ( invoice_id timeuuid, user_id uuid static, firstname text static, lastname text static, invoice_date timestamp static, payment_date timestamp static, total_amount decimal static, delivery_address text static, delivery_city text static, delivery_zipcode text static, item_id timeuuid, item_label text, item_price decimal, item_qty int, item_total decimal, primary key (invoice_id, item_id) ); Table
  • 23. Ippon Technologies © 2015#CassandraSummit Multi-criteria Search Mandatory Criteria ➔ User (implicit) ➔ Invoice date (range of dates) Additional Criteria ➔ Client lastname ➔ Client firstname ➔ City ➔ Zipcode Paginated Result
  • 24. Ippon Technologies © 2015#CassandraSummit Shall we use Solr ?
  • 25. Ippon Technologies © 2015#CassandraSummit Shall we use Solr ? ● Integrated in DataStax Enterprise ● Atomic and Automatic Index update ● Full-Text Search
  • 26. Ippon Technologies © 2015#CassandraSummit Shall we use Solr ? ● We search on static columns ➔ Solr don’t support them ● We search partitions ➔ Solr search lines
  • 27. Ippon Technologies © 2015#CassandraSummit Shall we use Solr ? ● We search on static columns ➔ Solr don’t support them ● We search partitions ➔ Solr search lines
  • 28. Ippon Technologies © 2015#CassandraSummit Shall we use secondary indexes ? ● Only one index used for a query ● Hard to get good performance with them
  • 29. Ippon Technologies © 2015#CassandraSummit Index Table Use index tables ➔ Partition Key : Mandatory criteria and one additional criterium ○ user_id ○ invoice day (truncated invoice date) ○ additional criterium ➔ Clustering columns : Invoice UUID
  • 30. Ippon Technologies © 2015#CassandraSummit Index Table
  • 31. Ippon Technologies © 2015#CassandraSummit Materialized view CREATE MATERIALIZED VIEW invoice_by_firstname AS SELECT invoice_id FROM invoice WHERE firstname IS NOT NULL PRIMARY KEY ((user_id, invoice_day, firstname), invoice_id) WITH CLUSTERING ORDER BY (invoice_id DESC) new in 3.0
  • 32. Ippon Technologies © 2015#CassandraSummit Parallel Search on indexes in memory merge by application
  • 33. Ippon Technologies © 2015#CassandraSummit Parallel item detail queries Result Page (id)
  • 34. Ippon Technologies © 2015#CassandraSummit Search Search on date range ➔ loop an every days in the range and stop when there is enough result for a page
  • 35. Ippon Technologies © 2015#CassandraSummit Search Complexity Query count ➔ For each day in date range ○ 1 query per additional criterium filled (partition by query) ➔ 1 query per item in result page (partition by query) Search Complexity ➔ partitions by query Example: 3 criteria, 7 days, 100 items per page ➔ query count ≤ 3 × 7 + 100 = 121
  • 37. Ippon Technologies © 2015#CassandraSummit Index — Instances @Repository public class InvoiceByLastNameRepository extends IndexRepository<String> { public InvoiceByLastNameRepository() { super("invoice_by_lastname", "lastname", Invoice::getLastName, Criteria::getLastName); } } @Repository public class InvoiceByFirstNameRepository extends IndexRepository<String> { public InvoiceByFirstNameRepository() { super("invoice_by_firstname", "firstname", Invoice::getFirstName, Criteria::getFirstName); } }
  • 38. Ippon Technologies © 2015#CassandraSummit Index — Parent Class public class IndexRepository<T> { @Inject private Session session; private final String tableName; private final String valueName; private final Function<Invoice, T> valueGetter; private final Function<Criteria, T> criteriumGetter; private PreparedStatement insertStmt; private PreparedStatement findStmt; private PreparedStatement findWithOffsetStmt; @PostConstruct public void init() { /* initialize PreparedStatements */ }
  • 39. Ippon Technologies © 2015#CassandraSummit Index — Insert @Override public void insert(Invoice invoice) { T value = valueGetter.apply(invoice); if (value != null) { session.execute( insertStmt.bind( invoice.getUserId(), Dates.toDate(invoice.getInvoiceDay()), value, invoice.getId())); } }
  • 40. Ippon Technologies © 2015#CassandraSummit Index — Insert — Prepare Statement insertStmt = session.prepare( QueryBuilder.insertInto(tableName) .value("user_id", bindMarker()) .value("invoice_day", bindMarker()) .value(valueName, bindMarker()) .value("invoice_id", bindMarker()) );
  • 41. Ippon Technologies © 2015#CassandraSummit Index — Insert — Date conversion public static Date toDate(LocalDate date) { return date == null ? null : Date.from(date.atStartOfDay().atZone(ZoneOffset.systemDefault()).toInstant()); }
  • 42. Ippon Technologies © 2015#CassandraSummit Index — Search @Override public CompletableFuture<Iterator<UUID>> find(Criteria criteria, LocalDate day, UUID offset) { T criterium = criteriumGetter.apply(criteria); if (criterium == null) { return CompletableFuture.completedFuture(null); } BoundStatement stmt; if (invoiceIdOffset == null) { stmt = findStmt.bind(criteria.getUserId(), Dates.toDate(day), criterium); } else { stmt = findWithOffsetStmt.bind(criteria.getUserId(), Dates.toDate(day), criterium, offset); } return Jdk8.completableFuture(session.executeAsync(stmt)) .thenApply(rs -> Iterators.transform(rs.iterator(), row -> row.getUUID(0))); }
  • 43. Ippon Technologies © 2015#CassandraSummit Index — Search — Prepare Statement findWithOffsetStmt = session.prepare( QueryBuilder.select() .column("invoice_id") .from(tableName) .where(eq("user_id", bindMarker())) .and(eq("invoice_day", bindMarker())) .and(eq(valueName, bindMarker())) .and(lte("invoice_id", bindMarker())) );
  • 44. Ippon Technologies © 2015#CassandraSummit Index — Search (Guava to Java 8) public static <T> CompletableFuture<T> completableFuture(ListenableFuture<T> guavaFuture) { CompletableFuture<T> future = new CompletableFuture<>(); Futures.addCallback(guavaFuture, new FutureCallback<T>() { @Override public void onSuccess(T result) { future.complete(result); } @Override public void onFailure(Throwable t) { future.completeExceptionally(t); } }); return future; }
  • 46. Ippon Technologies © 2015#CassandraSummit Service — Class @Service public class InvoiceSearchService { @Inject private InvoiceRepository invoiceRepository; @Inject private InvoiceByDayRepository byDayRepository; @Inject private InvoiceByLastNameRepository byLastNameRepository; @Inject private InvoiceByFirstNameRepository byLastNameRepository; @Inject private InvoiceByCityRepository byCityRepository; @Inject private InvoiceByZipCodeRepository byZipCodeRepository;
  • 47. Ippon Technologies © 2015#CassandraSummit Service — Search public ResultPage findByCriteria(Criteria criteria) { return byDateInteval(criteria, (crit, day, offset) -> { CompletableFuture<Iterator<UUID>> futureUuidIt; if (crit.hasIndexedCriteria()) { /* * ... Doing multi-criteria search; see next slide ... */ } else { futureUuidIt = byDayRepository.find(crit.getUserId(), day, offset); } return futureUuidIt; }); }
  • 48. Ippon Technologies © 2015#CassandraSummit Service — Search CompletableFuture<Iterator<UUID>>[] futures = Stream.<IndexRepository> of( byLastNameRepository, byFirstNameRepository, byCityRepository, byZipCodeRepository) .map(repo -> repo.find(crit, day, offset)) .toArray(CompletableFuture[]::new); futureUuidIt = CompletableFuture.allOf(futures).thenApply(v -> Iterators.intersection(TimeUUIDComparator.desc, Stream.of(futures) .map(CompletableFuture::join) .filter(Objects::nonNull) .collect(Collectors.toList())));
  • 49. Ippon Technologies © 2015#CassandraSummit Service — UUIDs Comparator /** * TimeUUID Comparator equivalent to Cassandra’s Comparator: * @see org.apache.cassandra.db.marshal.TimeUUIDType#compare() */ public enum TimeUUIDComparator implements Comparator<UUID> { desc { @Override public int compare(UUID o1, UUID o2) { long delta = o2.timestamp() - o1.timestamp(); if (delta != 0) return Ints.saturatedCast(delta); return o2.compareTo(o1); } }; }
  • 50. Ippon Technologies © 2015#CassandraSummit Service — Days Loop @FunctionalInterface private static interface DayQuery { CompletableFuture<Iterator<UUID>> find(Criteria criteria, LocalDate day, UUID invoiceIdOffset); } private ResultPage byDateInteval(Criteria criteria, DayQuery dayQuery) { int limit = criteria.getLimit(); List<Invoice> resultList = new ArrayList<>(limit); LocalDate dayOffset = criteria.getDayOffset(); UUID invoiceIdOffset = criteria.getInvoiceIdOffset(); /* ... Loop on days ; to be seen in next slide ... */ return new ResultPage(resultList); }
  • 51. Ippon Technologies © 2015#CassandraSummit Service — Days Loop LocalDate day = criteria.getLastDay(); do { Iterator<UUID> uuidIt = dayQuery.find(criteria, day, invoiceIdOffset).join(); limit -= loadInvoices(resultList, uuidIt, criteria, limit); if (uuidIt.hasNext()) { return new ResultPage(resultList, day, uuidIt.next()); } day = day.minusDays(1); invoiceIdOffset = null; } while (!day.isBefore(criteria.getFirstDay()));
  • 52. Ippon Technologies © 2015#CassandraSummit Service — Invoices Loading private int loadInvoices(List<Invoice> resultList, Iterator<UUID> uuidIt, int limit) { List<CompletableFuture<Invoice>> futureList = new ArrayList<>(limit); for (int i = 0; i < limit && uuidIt.hasNext(); ++i) { futureList.add(invoiceRepository.findOne(uuidIt.next())); } futureList.stream() .map(CompletableFuture::join) .forEach(resultList::add); return futureList.size(); }
  • 54. Ippon Technologies © 2015#CassandraSummit Limits ● We got an exact-match search ➔ No full text search ➔ No « start with » search ➔ No pattern base search ● Requires highly discriminating mandatory criteria ➔ user_id & invoice_day ● Pagination doesn’t give total item count ➔ Could be done with additionnal query cost ● No sort availaible
  • 55. Ippon Technologies © 2015#CassandraSummit Hardware ● Hosted by Ippon Hosting ● 8 nodes ➔ 16 Gb RAM ➔ Two SSD drives with 256 Gb in RAID 0 ● 6 nodes dedicated to Cassandra cluster ● 2 nodes dedicated to the application
  • 56. Ippon Technologies © 2015#CassandraSummit Application ● 5,000 concurrent users ● 9 months of data loaded ➔ Legacy system: store 1 year; search on last 3 months. ➔ Target: 3 years of history ● Real-time search Result ➔ Data are immediately available ➔ Legacy system: data available next day ● Cost Killer
  • 57. Q & A