SlideShare ist ein Scribd-Unternehmen logo
1 von 48
Downloaden Sie, um offline zu lesen
Using Lambda
Expressions to Query a
Datastore
Xavier Coulon - Red Hat
@xcoulon
The idea
The idea
Lambda Expressions:
• provide type safety
• describe the "what", not the "how"
The idea
The idea
u -> ( u.firstName.equals("john") && u.lastName.equals("doe"))
|| u.userName.equals("jdoe"))
final List<User> users = userCollection.filter(
u -> ( u.firstName.equals("john") && u.lastName.equals("doe"))
|| u.userName.equals("jdoe")).toList();
Introducing project
Lambdamatic
Part I. The building blocks
Building blocks
• Metamodel generation
• Lambda Expression analysis
Metamodel generation
(à la JPA)
package com.example.domain;
public class User {
private String id;
private String firstName;
private String lastName;
private String userName;
}
Metamodel generation
package com.example.domain;
@Document(collection="users")
public class User {
@DocumentId
private String id;
@DocumentField
private String firstName;
private String lastName;
@DocumentField(name="uName")
private String userName;
}
package com.example.domain;
@Generated(value="LambdamaticAnnotationsProcessor")
public class QUser implements QueryMetadata<User> {
@DocumentField(name="_id")
public StringField firstName;
@DocumentField(name="firstName")
public StringField firstName;
@DocumentField(name="lastName")
public StringField lastName;
@DocumentField(name="uName")
public StringField userName;
}
Query Metadata class generation
Metamodel generation
package com.example.domain;
@Generated(value="o.l.m.a.DocumentAnnotationProcessor")
public class UserCollection extends
LambdamaticMongoCollectionImpl<User, QUser> {
public UserCollection(final MongoClient mongoClient,
final String databaseName) {
super(mongoClient, databaseName, "users", User.class);
}
}
Collection class
package com.example.domain;
@Document(collection="users")
public class User {
@DocumentId
private String id;
@DocumentField
private String firstName;
private String lastName;
@DocumentField(name="uName")
private String userName;
}
Metamodel generation
CDI Integration
@Generated(value="org.lambdamatic.mongodb.apt.DocumentAnnotationProcessor")
@ApplicationScoped
public class UserCollectionProducer {
@Produces
public UserCollection getUserCollection(final MongoClient mongoClient,
final MongoClientConfiguration mongoClientConfiguration) {
return new UserCollection(mongoClient, mongoClientConfiguration.getDatabaseName(), "users");
}
}
final List<User> users = userCollection.filter(
u -> ( u.firstName.equals("john") && u.lastName.equals("doe"))
|| u.userName.equals("jdoe")).toList();
Metamodel in action
public class UserCollection extends
LambdamaticMongoCollectionImpl<User, QUser> {
...
}
package com.example.domain;
@Generated(value="LambdamaticAnnotationsProcessor")
public class QUser implements QueryMetadata<User> {
@DocumentField(name="_id")
public StringField firstName;
@DocumentField(name="firstName")
public StringField firstName;
...
}
Metamodel benefits
Geospatial queries
Metamodel benefits
public class Location {
/** The latitude value.*/
private double latitude;
/** The longitude value.*/
private double longitude;
}
public List<BikeStation> findWithin(final Location[] corners) {
return bikeStationCollection.find(s -> s.location.geoWithin(corners))
.toList();
}
public class QBikeStation implements QueryMetadata<BikeStation> {
@DocumentField(name="location")
public LocationField location;
...
}
@Document(collection="bikestations")
public class BikeStation {
@DocumentField
private Location location;
...
}
public interface LocationField {
public boolean geoWithin(final Location[] corners);
...
}
Lambda Expression
Analysis
(this is the fun part, really)
Lambda Expression
Analysis
Lambda Expression
Analysis
@FunctionalInterface
public interface FilterExpression<T> extends Predicate<T>, Serializable { }
Step#1 : Use a Serializable Functional Interface
Lambda Expression
Analysis
public static <T> SerializedLambda getSerializedLambda(
final FilterExpression<T> expression) {
...
final Class<?> cl = expression.getClass();
final Method m = cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
return (SerializedLambda) m.invoke(expression);
...
}
Step#2 : Locate the generated method
Lambda Expression
Analysis
Step#3 : read the generated bytecode
Label L1125736023
VarInsn ALOAD #0
FieldInsn GETFIELD com/sample/QUser.firstName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;)
LdcInsn john
MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z)
JumpInsn IFEQ L1636182655
VarInsn ALOAD #0
FieldInsn GETFIELD com/sample/QUser.lastName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;)
Label L1122606666
LdcInsn doe
MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z)
JumpInsn IFNE L350068407
Label L1636182655
VarInsn ALOAD #0
FieldInsn GETFIELD com/sample/QUser.userName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;)
LdcInsn jdoe
MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z)
JumpInsn IFNE L350068407
Insn ICONST_0
JumpInsn GOTO L1820383114
Label L350068407
Insn ICONST_1
Label L1820383114
Insn IRETURN
Label L369049246
LocalVariable u (desc=Lcom/sample/QUser;) index=0
Lambda Expression
Analysis
Step#4 : build an AST
if(u.firstName.equals("john")) {
if(u.lastName.equals("doe")) {
return true
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
}
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
}
if(u.firstName.equals("john")) {
if(u.lastName.equals("doe")) {
return true
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
}
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
}
if(u.firstName.equals("john")) {
if(u.lastName.equals("doe")) {
return true
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
}
} else {
if(u.userName.equals("jdoe")) {
return true
} else {
return false
}
(u.firstName.equals("john")
&& u.lastName.equals("doe"))
|| (u.firstName.equals("john")
&& !u.lastName.equals("doe")
&& u.userName.equals("jdoe"))
|| (!u.firstName.equals("john")
&& u.userName.equals("jdoe"))
Lambda Expression
Analysis
Step#5 : Thin out the AST
(u.firstName.equals("john")
&& u.lastName.equals("doe"))
|| (u.firstName.equals("john")
&& !u.lastName.equals("doe")
&& u.userName.equals("jdoe"))
|| (!u.firstName.equals("john")
&& u.userName.equals("jdoe"))
Lambda Expression
Analysis
Step#6 : Further simplify the AST
(u.firstName.equals("john")
&& u.lastName.equals("doe"))
|| (u.firstName.equals("john")
&& !u.lastName.equals("doe")
&& u.userName.equals("jdoe"))
|| (!u.firstName.equals("john")
&& u.userName.equals("jdoe"))
Lambda Expression
Analysis
Boolean algebra to the rescue !
a.(b.c) = a.b.c
a + (b + c) = a + b + c
a.(!a + b).(!a + c) = a.b.c
a + (!a.b) + (!a.c) = a + b + c
a.(a + b).(a + c) = a
a + (a.b) + (a.c) = a
(a.b) + (a.c) + (a.d) = a.(b + c + d)
(a + b).(a + c).(a + d) = a + (b.c.d)
a + a = a
a.a = a
a.!a = O
a + !a = I
O + a = a
O.a = O
1 + a = 1
1.a = a
a.(b + c + d) = (a.b) + (a.c) + (a.d)
a + (b.c.d) = (a + b).(a + c).(a + d)
Lambda Expression
Analysis
Step#6 : further simplify the statement tree
(u.firstName.equals("john")
&& u.lastName.equals("doe"))
|| (u.firstName.equals("john")
&& !u.lastName.equals("doe")
&& u.userName.equals("jdoe"))
|| (!u.firstName.equals("john")
&& u.userName.equals("jdoe"))
(u.firstName.equals("john") && u.lastName.equals("doe")) || u.userName.equals("jdoe")
Performances ?
• Byte code is analyzed on first access to Lambda
Expression ( <100ms)
• "Raw" AST is cached for subsequent calls
• Placeholders in AST for captured arguments
Part II. Managing data on
MongoDB
Managing Data on
MongoDB
• Providing Codecs for Lambda Expressions and
Documents
• Skipping the "DBObject" DTOs layer
MongoDB Java Driver Integration
Querying MongoDB
Service
Layer
Lambda
Expression
MongoDB
Java Driver
BSON
Document
MongoDB
FilterExpression
Codec
BSON
Document
Domain
object(s)
Document
Codec
Demo #1
Geolocation queries
Three more things
(yes, three)
Query on Arrays
Query on Arrays
Query on Arrays
final List<BlogEntry> blogEntries =
blogEntryCollection.filter(
e -> e.comments.elementMatch(
c -> c.author.equals("anonymous") && c.date.greaterOrEquals(twoDaysAgo)))
.toList();
final List<BlogEntry> blogEntries =
blogEntryCollection.filter(
e -> e.comments.author.equals("anonymous") && 

e.comments.date.greaterOrEquals(twoDaysAgo))
.toList();
Query Projections
Query Projection
Projection Metadata class generation
@Generated(value="o.l.m.a.DocumentAnnotationProcessor")
public abstract class PBlogEntry
implements ProjectionMetadata<BlogEntry> {
@DocumentField(name="_id")
public ProjectionField id;
@DocumentField(name="authorName")
public ProjectionField authorName;
@DocumentField(name="publishDate")
public ProjectionField publishDate;
...
}
@Document(collection="blog")
public class BlogEntry {
@DocumentId
private String id;
@DocumentField
private String authorName;
private Date publishDate;
...
}
Query Projection
import static org.lambdamatic.mongodb.Projection.include;
final BlogEntry blogEntry = blogEntries.filter(e -> e.id.equals("1"))
.projection(e -> include(e.authorName, e.title, e.publishDate))
.first();
@Generated(value="o.l.m.a.DocumentAnnotationProcessor")
public abstract class PBlogEntry
implements ProjectionMetadata<BlogEntry> {
@DocumentField(name="_id")
public ProjectionField id;
@DocumentField(name="authorName")
public ProjectionField authorName;
@DocumentField(name="publishDate")
public ProjectionField publishDate;
...
}
public interface Projection {
@IncludeFields
public static void include(final ProjectionField... fields) {}
@ExcludeFields
public static void exclude(final ProjectionField... fields) {}
}
Query Projection
Projecting array elements
final BlogEntry blogEntry = blogEntryCollection.filter(e -> e.id.equals("1"))
.projection(e -> include(e.authorName, e.title, e.publishDate,
e.comments.elementMatch(c -> c.author.equals("anonymous") &&
c.date.greaterOrEquals(twoDaysAgo))))
.first();
Update Operations
Update Operations
@Document(collection="blog")
public class BlogEntry {
@DocumentId
private String id;
/** Name of author of the blog entry. */
private String authorName;
/** Title of the Blog Entry */
private String title;
/** list of comments. */
private List<BlogEntryComment> comments;
...
}
Update Metadata class generation
@Generated(value="o.l.m.a.DocumentAnnotationProcessor")
public abstract class UBlogEntry implements UpdateMetadata<BlogEntry> {
@DocumentField(name="_id")
public String id;
@DocumentField(name="authorName")
public String authorName;
@DocumentField(name="title")
public String title;
@DocumentField(name="comments")
public UBlogEntryCommentArray comments;
...
}
Update Operations
BlogEntryComment comment = ... ;
blogEntries.filter(e -> e.id.equals("1")).
forEach(e -> {
e.lastUpdate = new Date();
e.commentsNumber++;
e.comments.push(comment);});
@Document(collection="blog")
public class BlogEntry {
@DocumentId
private String id;
/** date of last update. */
private Date lastUpdate;
/** Number of comments */
private int commentsNumber;
/** list of comments. */
private List<BlogEntryComment> comments;
@EmbeddedDocument
public class BlogEntryComment {
/** comment author. */
private String author;
/** comment date. */
private Date date;
/** comment content. */
private String content;
Demo #2
Filter with projections
and Update
Project Status
Experimental
Project Info
http://github.com/lambdamatic
• Give it a try !
• Clone it / Fork it / Star it
• Open issues to discuss about API and features
Thanks !
Q/A

Weitere ähnliche Inhalte

Was ist angesagt?

11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
Phúc Đỗ
 
TclOO: Past Present Future
TclOO: Past Present FutureTclOO: Past Present Future
TclOO: Past Present Future
Donal Fellows
 
Breaking down data silos with the open data protocol
Breaking down data silos with the open data protocolBreaking down data silos with the open data protocol
Breaking down data silos with the open data protocol
Woodruff Solutions LLC
 
Optimizing Tcl Bytecode
Optimizing Tcl BytecodeOptimizing Tcl Bytecode
Optimizing Tcl Bytecode
Donal Fellows
 

Was ist angesagt? (20)

C# 7
C# 7C# 7
C# 7
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
Grammarware Memes
Grammarware MemesGrammarware Memes
Grammarware Memes
 
Collectors in the Wild
Collectors in the WildCollectors in the Wild
Collectors in the Wild
 
Functional Algebra: Monoids Applied
Functional Algebra: Monoids AppliedFunctional Algebra: Monoids Applied
Functional Algebra: Monoids Applied
 
TclOO: Past Present Future
TclOO: Past Present FutureTclOO: Past Present Future
TclOO: Past Present Future
 
Breaking down data silos with the open data protocol
Breaking down data silos with the open data protocolBreaking down data silos with the open data protocol
Breaking down data silos with the open data protocol
 
Lombokの紹介
Lombokの紹介Lombokの紹介
Lombokの紹介
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
360|iDev
360|iDev360|iDev
360|iDev
 
G3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy AnnotationsG3 Summit 2016 - Taking Advantage of Groovy Annotations
G3 Summit 2016 - Taking Advantage of Groovy Annotations
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Making an Object System with Tcl 8.5
Making an Object System with Tcl 8.5Making an Object System with Tcl 8.5
Making an Object System with Tcl 8.5
 
Optimizing Tcl Bytecode
Optimizing Tcl BytecodeOptimizing Tcl Bytecode
Optimizing Tcl Bytecode
 

Andere mochten auch (7)

Build and Deploy on OpenShift
Build and Deploy on OpenShiftBuild and Deploy on OpenShift
Build and Deploy on OpenShift
 
EclipseCon Europe 2016 - Docker Tooling for Developers
EclipseCon Europe 2016 - Docker Tooling for DevelopersEclipseCon Europe 2016 - Docker Tooling for Developers
EclipseCon Europe 2016 - Docker Tooling for Developers
 
Docker Tooling for Java EE Developers
Docker Tooling for Java EE  DevelopersDocker Tooling for Java EE  Developers
Docker Tooling for Java EE Developers
 
Eclipse DemoCamp Munich - Docker Tooling and Vagrant Tooling
Eclipse DemoCamp Munich  - Docker Tooling and Vagrant ToolingEclipse DemoCamp Munich  - Docker Tooling and Vagrant Tooling
Eclipse DemoCamp Munich - Docker Tooling and Vagrant Tooling
 
Red Hat Mobile
Red Hat MobileRed Hat Mobile
Red Hat Mobile
 
Eclipse Neon Webinar - Docker Tooling for Developers
Eclipse Neon Webinar - Docker Tooling for DevelopersEclipse Neon Webinar - Docker Tooling for Developers
Eclipse Neon Webinar - Docker Tooling for Developers
 
OpenShift Enterprise
OpenShift EnterpriseOpenShift Enterprise
OpenShift Enterprise
 

Ähnlich wie DevNation'15 - Using Lambda Expressions to Query a Datastore

Os Vanrossum
Os VanrossumOs Vanrossum
Os Vanrossum
oscon2007
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 

Ähnlich wie DevNation'15 - Using Lambda Expressions to Query a Datastore (20)

Xm lparsers
Xm lparsersXm lparsers
Xm lparsers
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Lambdas: Myths and Mistakes
Lambdas: Myths and MistakesLambdas: Myths and Mistakes
Lambdas: Myths and Mistakes
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
The... Wonderful? World of Lambdas
The... Wonderful? World of LambdasThe... Wonderful? World of Lambdas
The... Wonderful? World of Lambdas
 
Object-oriented Basics
Object-oriented BasicsObject-oriented Basics
Object-oriented Basics
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 
Introduction to Python , Overview
Introduction to Python , OverviewIntroduction to Python , Overview
Introduction to Python , Overview
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
 
Os Vanrossum
Os VanrossumOs Vanrossum
Os Vanrossum
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Xml parsers
Xml parsersXml parsers
Xml parsers
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Scala coated JVM
Scala coated JVMScala coated JVM
Scala coated JVM
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Major Java 8 features
Major Java 8 featuresMajor Java 8 features
Major Java 8 features
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 

Kürzlich hochgeladen

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Kürzlich hochgeladen (20)

Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 

DevNation'15 - Using Lambda Expressions to Query a Datastore

  • 1. Using Lambda Expressions to Query a Datastore Xavier Coulon - Red Hat @xcoulon
  • 3. The idea Lambda Expressions: • provide type safety • describe the "what", not the "how"
  • 5. The idea u -> ( u.firstName.equals("john") && u.lastName.equals("doe")) || u.userName.equals("jdoe")) final List<User> users = userCollection.filter( u -> ( u.firstName.equals("john") && u.lastName.equals("doe")) || u.userName.equals("jdoe")).toList();
  • 7. Part I. The building blocks
  • 8. Building blocks • Metamodel generation • Lambda Expression analysis
  • 10. package com.example.domain; public class User { private String id; private String firstName; private String lastName; private String userName; } Metamodel generation package com.example.domain; @Document(collection="users") public class User { @DocumentId private String id; @DocumentField private String firstName; private String lastName; @DocumentField(name="uName") private String userName; } package com.example.domain; @Generated(value="LambdamaticAnnotationsProcessor") public class QUser implements QueryMetadata<User> { @DocumentField(name="_id") public StringField firstName; @DocumentField(name="firstName") public StringField firstName; @DocumentField(name="lastName") public StringField lastName; @DocumentField(name="uName") public StringField userName; } Query Metadata class generation
  • 11. Metamodel generation package com.example.domain; @Generated(value="o.l.m.a.DocumentAnnotationProcessor") public class UserCollection extends LambdamaticMongoCollectionImpl<User, QUser> { public UserCollection(final MongoClient mongoClient, final String databaseName) { super(mongoClient, databaseName, "users", User.class); } } Collection class package com.example.domain; @Document(collection="users") public class User { @DocumentId private String id; @DocumentField private String firstName; private String lastName; @DocumentField(name="uName") private String userName; }
  • 12. Metamodel generation CDI Integration @Generated(value="org.lambdamatic.mongodb.apt.DocumentAnnotationProcessor") @ApplicationScoped public class UserCollectionProducer { @Produces public UserCollection getUserCollection(final MongoClient mongoClient, final MongoClientConfiguration mongoClientConfiguration) { return new UserCollection(mongoClient, mongoClientConfiguration.getDatabaseName(), "users"); } }
  • 13. final List<User> users = userCollection.filter( u -> ( u.firstName.equals("john") && u.lastName.equals("doe")) || u.userName.equals("jdoe")).toList(); Metamodel in action public class UserCollection extends LambdamaticMongoCollectionImpl<User, QUser> { ... } package com.example.domain; @Generated(value="LambdamaticAnnotationsProcessor") public class QUser implements QueryMetadata<User> { @DocumentField(name="_id") public StringField firstName; @DocumentField(name="firstName") public StringField firstName; ... }
  • 15. Metamodel benefits public class Location { /** The latitude value.*/ private double latitude; /** The longitude value.*/ private double longitude; } public List<BikeStation> findWithin(final Location[] corners) { return bikeStationCollection.find(s -> s.location.geoWithin(corners)) .toList(); } public class QBikeStation implements QueryMetadata<BikeStation> { @DocumentField(name="location") public LocationField location; ... } @Document(collection="bikestations") public class BikeStation { @DocumentField private Location location; ... } public interface LocationField { public boolean geoWithin(final Location[] corners); ... }
  • 16. Lambda Expression Analysis (this is the fun part, really)
  • 18.
  • 19. Lambda Expression Analysis @FunctionalInterface public interface FilterExpression<T> extends Predicate<T>, Serializable { } Step#1 : Use a Serializable Functional Interface
  • 20. Lambda Expression Analysis public static <T> SerializedLambda getSerializedLambda( final FilterExpression<T> expression) { ... final Class<?> cl = expression.getClass(); final Method m = cl.getDeclaredMethod("writeReplace"); m.setAccessible(true); return (SerializedLambda) m.invoke(expression); ... } Step#2 : Locate the generated method
  • 21. Lambda Expression Analysis Step#3 : read the generated bytecode Label L1125736023 VarInsn ALOAD #0 FieldInsn GETFIELD com/sample/QUser.firstName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;) LdcInsn john MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z) JumpInsn IFEQ L1636182655 VarInsn ALOAD #0 FieldInsn GETFIELD com/sample/QUser.lastName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;) Label L1122606666 LdcInsn doe MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z) JumpInsn IFNE L350068407 Label L1636182655 VarInsn ALOAD #0 FieldInsn GETFIELD com/sample/QUser.userName (desc=Lorg/lambdamatic/mongodb/metadata/StringField;) LdcInsn jdoe MethodInsn INVOKEVIRTUAL java/lang/Object.equals (desc=(Ljava/lang/Object;)Z) JumpInsn IFNE L350068407 Insn ICONST_0 JumpInsn GOTO L1820383114 Label L350068407 Insn ICONST_1 Label L1820383114 Insn IRETURN Label L369049246 LocalVariable u (desc=Lcom/sample/QUser;) index=0
  • 22. Lambda Expression Analysis Step#4 : build an AST if(u.firstName.equals("john")) { if(u.lastName.equals("doe")) { return true } else { if(u.userName.equals("jdoe")) { return true } else { return false } } } else { if(u.userName.equals("jdoe")) { return true } else { return false } }
  • 23. if(u.firstName.equals("john")) { if(u.lastName.equals("doe")) { return true } else { if(u.userName.equals("jdoe")) { return true } else { return false } } } else { if(u.userName.equals("jdoe")) { return true } else { return false } } if(u.firstName.equals("john")) { if(u.lastName.equals("doe")) { return true } else { if(u.userName.equals("jdoe")) { return true } else { return false } } } else { if(u.userName.equals("jdoe")) { return true } else { return false } (u.firstName.equals("john") && u.lastName.equals("doe")) || (u.firstName.equals("john") && !u.lastName.equals("doe") && u.userName.equals("jdoe")) || (!u.firstName.equals("john") && u.userName.equals("jdoe")) Lambda Expression Analysis Step#5 : Thin out the AST
  • 24. (u.firstName.equals("john") && u.lastName.equals("doe")) || (u.firstName.equals("john") && !u.lastName.equals("doe") && u.userName.equals("jdoe")) || (!u.firstName.equals("john") && u.userName.equals("jdoe")) Lambda Expression Analysis Step#6 : Further simplify the AST (u.firstName.equals("john") && u.lastName.equals("doe")) || (u.firstName.equals("john") && !u.lastName.equals("doe") && u.userName.equals("jdoe")) || (!u.firstName.equals("john") && u.userName.equals("jdoe"))
  • 25. Lambda Expression Analysis Boolean algebra to the rescue ! a.(b.c) = a.b.c a + (b + c) = a + b + c a.(!a + b).(!a + c) = a.b.c a + (!a.b) + (!a.c) = a + b + c a.(a + b).(a + c) = a a + (a.b) + (a.c) = a (a.b) + (a.c) + (a.d) = a.(b + c + d) (a + b).(a + c).(a + d) = a + (b.c.d) a + a = a a.a = a a.!a = O a + !a = I O + a = a O.a = O 1 + a = 1 1.a = a a.(b + c + d) = (a.b) + (a.c) + (a.d) a + (b.c.d) = (a + b).(a + c).(a + d)
  • 26.
  • 27. Lambda Expression Analysis Step#6 : further simplify the statement tree (u.firstName.equals("john") && u.lastName.equals("doe")) || (u.firstName.equals("john") && !u.lastName.equals("doe") && u.userName.equals("jdoe")) || (!u.firstName.equals("john") && u.userName.equals("jdoe")) (u.firstName.equals("john") && u.lastName.equals("doe")) || u.userName.equals("jdoe")
  • 28.
  • 29. Performances ? • Byte code is analyzed on first access to Lambda Expression ( <100ms) • "Raw" AST is cached for subsequent calls • Placeholders in AST for captured arguments
  • 30. Part II. Managing data on MongoDB
  • 31. Managing Data on MongoDB • Providing Codecs for Lambda Expressions and Documents • Skipping the "DBObject" DTOs layer MongoDB Java Driver Integration
  • 37. Query on Arrays final List<BlogEntry> blogEntries = blogEntryCollection.filter( e -> e.comments.elementMatch( c -> c.author.equals("anonymous") && c.date.greaterOrEquals(twoDaysAgo))) .toList(); final List<BlogEntry> blogEntries = blogEntryCollection.filter( e -> e.comments.author.equals("anonymous") && 
 e.comments.date.greaterOrEquals(twoDaysAgo)) .toList();
  • 39. Query Projection Projection Metadata class generation @Generated(value="o.l.m.a.DocumentAnnotationProcessor") public abstract class PBlogEntry implements ProjectionMetadata<BlogEntry> { @DocumentField(name="_id") public ProjectionField id; @DocumentField(name="authorName") public ProjectionField authorName; @DocumentField(name="publishDate") public ProjectionField publishDate; ... } @Document(collection="blog") public class BlogEntry { @DocumentId private String id; @DocumentField private String authorName; private Date publishDate; ... }
  • 40. Query Projection import static org.lambdamatic.mongodb.Projection.include; final BlogEntry blogEntry = blogEntries.filter(e -> e.id.equals("1")) .projection(e -> include(e.authorName, e.title, e.publishDate)) .first(); @Generated(value="o.l.m.a.DocumentAnnotationProcessor") public abstract class PBlogEntry implements ProjectionMetadata<BlogEntry> { @DocumentField(name="_id") public ProjectionField id; @DocumentField(name="authorName") public ProjectionField authorName; @DocumentField(name="publishDate") public ProjectionField publishDate; ... } public interface Projection { @IncludeFields public static void include(final ProjectionField... fields) {} @ExcludeFields public static void exclude(final ProjectionField... fields) {} }
  • 41. Query Projection Projecting array elements final BlogEntry blogEntry = blogEntryCollection.filter(e -> e.id.equals("1")) .projection(e -> include(e.authorName, e.title, e.publishDate, e.comments.elementMatch(c -> c.author.equals("anonymous") && c.date.greaterOrEquals(twoDaysAgo)))) .first();
  • 43. Update Operations @Document(collection="blog") public class BlogEntry { @DocumentId private String id; /** Name of author of the blog entry. */ private String authorName; /** Title of the Blog Entry */ private String title; /** list of comments. */ private List<BlogEntryComment> comments; ... } Update Metadata class generation @Generated(value="o.l.m.a.DocumentAnnotationProcessor") public abstract class UBlogEntry implements UpdateMetadata<BlogEntry> { @DocumentField(name="_id") public String id; @DocumentField(name="authorName") public String authorName; @DocumentField(name="title") public String title; @DocumentField(name="comments") public UBlogEntryCommentArray comments; ... }
  • 44. Update Operations BlogEntryComment comment = ... ; blogEntries.filter(e -> e.id.equals("1")). forEach(e -> { e.lastUpdate = new Date(); e.commentsNumber++; e.comments.push(comment);}); @Document(collection="blog") public class BlogEntry { @DocumentId private String id; /** date of last update. */ private Date lastUpdate; /** Number of comments */ private int commentsNumber; /** list of comments. */ private List<BlogEntryComment> comments; @EmbeddedDocument public class BlogEntryComment { /** comment author. */ private String author; /** comment date. */ private Date date; /** comment content. */ private String content;
  • 45. Demo #2 Filter with projections and Update
  • 47. Project Info http://github.com/lambdamatic • Give it a try ! • Clone it / Fork it / Star it • Open issues to discuss about API and features