Slide 1

Slide 1 text

1 August  15,  2012 Open  source,  high  performance  database LINQ in the C#/.NET Driver Robert Stam Software Engineer, 10gen Wednesday, August 15, 12

Slide 2

Slide 2 text

• Added in the 1.4 release • Enhanced in 1.4.1, 1.4.2 and 1.5 • Think of LINQ as just another way to write your queries • A higher level of abstraction: write your queries in C# • A data-source neutral query language 2 LINQ support in the C#/.NET driver Wednesday, August 15, 12

Slide 3

Slide 3 text

3 • Typical  na=ve  query > db.employees.find({ Name : /^John/ Salary : { $gte : 100000 } }) { Name : "John Doe", Salary : 120000, .... } ... > Native queries (in the mongo shell) Wednesday, August 15, 12

Slide 4

Slide 4 text

4 • Typical  na=ve  query  in  C# var collection = database.GetCollection("employees"); var query = Query.And( Query.Matches("Name", "/^John/"), Query.GTE("Salary", 100000) ); foreach (var employee in collection.Find(query)) { // process employee } Native queries (in C#) Wednesday, August 15, 12

Slide 5

Slide 5 text

5 • LINQ  is  supported  for  queries  only  (although   Query.Where  supports  wri=ng  predicates  in  C#   that  can  be  used  with  Update) • You  opt-­‐in  to  LINQ  using  AsQueryable() Using LINQ for queries Wednesday, August 15, 12

Slide 6

Slide 6 text

6 • Typical  query  using  LINQ var collection = database.GetCollection("employees"); var query = from e in collection.AsQueryable() where e.Name.StartsWith("John") && e.Salary >= 100000 select e; foreach (var employee in query) { // process employee } Using LINQ for queries Wednesday, August 15, 12

Slide 7

Slide 7 text

7 • C#  compiler  creates  an  Expression  tree • C#/.NET  driver  translates  the  Expression  tree  to  an   equivalent  MongoDB  query  at  run  =me • Requirements – For  each  C#  property  referenced  in  the  LINQ  query  the   driver  has  to  be  able  to  figure  out  the  matching  element   name  in  the  BSON  document  (using  doZed  names  for   nested  elements) – For  each  test  using  those  C#  proper=es  the  driver  has  to  be   be  able  to  translate  the  test  into  an  equivalent  MongoDB   query  operator What's really happening when you use LINQ? Wednesday, August 15, 12

Slide 8

Slide 8 text

8 • The  primary  goal  is:  we  will  only  support  LINQ  queries   that  have  a  reasonable  transla=on  to  an  equivalent   MongoDB  query • The  reason:  we  want  to  ensure  predictable   performance  from  LINQ  queries  (no  black  magic,  no   surprises) • So,  you  will  not  find: – Any  hidden  map/reduce  or  Javascript  tricks – Any  hidden  client  side  processing • Online  LINQ  tutorial  at:  hZp://www.mongodb.org/display/DOCS/ CSharp+Driver+LINQ+Tutorial Design goals of the LINQ support Wednesday, August 15, 12

Slide 9

Slide 9 text

9 var query = from e in collection.AsQueryable() where e.EmployeeStatus == Status.Active select e; // translates to (assuming enum value for Active is 1): { EmployeeStatus : 1 } var query = from e in collection.AsQueryable() where e.EmployeeStatus != Status.Active select e; // translates to: { EmployeeStatus : { $ne : 1 } } Sample LINQ queries (== and !=) Wednesday, August 15, 12

Slide 10

Slide 10 text

10 var query = from e in collection.AsQueryable() where e.EmployeeStatus == Status.Active && e.Salary > 100000 select e; // translates to: { EmployeeStatus : 1, Salary : { $gt : 100000 } } Sample LINQ queries (&&) Wednesday, August 15, 12

Slide 11

Slide 11 text

11 var query = from e in collection.AsQueryable() where e.EmployeeStatus == Status.Active || e.Salary > 100000 select e; // translates to: { $or : [ { EmployeeStatus : 1 }, { Salary : { $gt : 100000 } } ]} Sample LINQ queries (||) Wednesday, August 15, 12

Slide 12

Slide 12 text

12 var query = from e in collection.AsQueryable() where e.Name.Contains("oh") select e; // translates to: { nm: /oh/s } var query = from e in collection.AsQueryable() where e.Name.StartsWith("John") select e; // translates to: { nm: /^John/s } Sample LINQ queries (string Contains, StartsWith) Wednesday, August 15, 12

Slide 13

Slide 13 text

13 var query = from e in collection.AsQueryable() where e.Name.Length == 4 select e; // translates to: { nm: /^.{4}$/s } var query = from e in collection.AsQueryable() where string.IsNullOrEmpty(e.Name) select e; // translates to: { $or : [ { nm: { $type : 10 } }, { nm: "" } ] } Sample LINQ queries (string Length, IsNullOrEmpty) Wednesday, August 15, 12

Slide 14

Slide 14 text

14 var query = from e in collection.AsQueryable() where e.Name.ToLower() == "john macadam" select e; // translates to: { nm: /^john macadam$/is } Sample LINQ queries (string ToLower) Wednesday, August 15, 12

Slide 15

Slide 15 text

15 var query = from e in collection.AsQueryable() where e.Skills[0] == "Java" select e; // translates to: { "Skills.0" : "Java" } var query = from e in collection.AsQueryable() where e.Skills.Length == 3 select e; // translates to: { Skills : { $size : 3 } } Sample LINQ queries (array element, Length) Wednesday, August 15, 12

Slide 16

Slide 16 text

16 var query = from e in collection.AsQueryable() where e.Address.City == "Hoboken" select e; // translates to: { "Address.City" : "Hoboken" } Sample LINQ queries (dotted names) Wednesday, August 15, 12

Slide 17

Slide 17 text

17 var states = new [] { "NJ", "NY", "PA" }; var query = from e in collection.AsQueryable() where states.Contains(e.Address.State) select e; // translates to: { "Address.State" : { $in : [ "NJ", "NY", "PA" ] } } // alternative syntax using C#/.NET driver "In" method var query = from e in collection.AsQueryable() where e.Address.State.In(states) select e; Sample LINQ queries ($in) Wednesday, August 15, 12

Slide 18

Slide 18 text

18 var desiredSkills = new [] { "Java", "C#" }; var query = from e in collection.AsQueryable() where e.Skills.ContainsAny(desiredSkills) select e; // translates to: { "Skills" : { $in : [ "Java", "C#" ] } } var query = from e in collection.AsQueryable() where e.Skills.ContainsAll(desiredSkills) select e; // translates to: { "Skills" : { $all : [ "Java", "C#" ] } } note: ContainsAny and ContainsAll are defined by the C#/.NET driver and are not part of standard LINQ Sample LINQ queries ($in/$all with arrays) Wednesday, August 15, 12

Slide 19

Slide 19 text

19 var query = from e in collection.AsQueryable() where e.Addresses.Any(a => a.City == "Hoboken" && a.State == "NJ") select e; // translates to: { "Addresses" : { $elemMatch : { City : "Hoboken", State : "NJ" } } } Sample LINQ queries ($elemMatch) Wednesday, August 15, 12

Slide 20

Slide 20 text

20 • You  can  "Inject"  na=ve  MongoDB  queries  into  a  LINQ   query  if  you  need  to  include  a  test  that  LINQ  doesn't   support,  without  giving  up  LINQ  en=rely var query = from e in collection.AsQueryable() where e.Salary > 50000 && Query.NotExists("EmployeeStatus").Inject() select e; // translates to: { Salary : { $gt : 50000 }, EmployeeStatus : { $exists : false } } Mixing LINQ with MongoDB queries Wednesday, August 15, 12

Slide 21

Slide 21 text

21   Open  source,  high  performance  database Q&A Robert Stam Software Engineer, 10gen Wednesday, August 15, 12