DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Databases
  4. RavenDB… What am I Persisting, What am I Querying? (part 3)

RavenDB… What am I Persisting, What am I Querying? (part 3)

Phillip Haydon user avatar by
Phillip Haydon
·
Aug. 04, 12 · Interview
Like (0)
Save
Tweet
Share
3.90K Views

Join the DZone community and get the full member experience.

Join For Free

In part 3 I want to show you how to query References.

In the previous post I showed you three basic classes that demonstrate a Relationship between Order and OrderLine, and a Reference to User from Order using the UserId.

I’ve setup some really basic test data:

using (var session = store.OpenSession())
{
    session.Store(new User
    {
        FirstName = "Phillip",
        Surname = "Haydon",
        Username = "phillip.haydon",
        Password = "somepassword"
    });
    session.Store(new User
    {
        FirstName = "Edward",
        Surname = "Norton",
        Username = "edward.norton",
        Password = "somepassword"
    });
    session.Store(new Order
    {
        UserId = "users/1",
        DateOrdered = DateTime.Now,
        DateUpdated = DateTime.Now,
        Status = "Ordered",
        Lines = new List<OrderLine>
        {
            new OrderLine
            {
                Discount = 0m,
                PricePerUnit = 13.95m,
                Quantity = 5,
                SkuCode = "SN78"
            },
            new OrderLine
            {
                Discount = 0m,
                PricePerUnit = 13.95m,
                Quantity = 5,
                SkuCode = "SN78"
            }
        }
    });

    session.SaveChanges();
}

This creates two collections:

image

With our Order document looking like:

{
  "UserId": "users/1",
  "DateOrdered": "2012-07-13T23:34:40.5542680",
  "DateUpdated": "2012-07-13T23:34:40.5542680",
  "Status": "Ordered",
  "Lines": [
    {
      "PricePerUnit": 13.95,
      "Quantity": 5,
      "Discount": 0.0,
      "SkuCode": "SN78"
    },
    {
      "PricePerUnit": 13.95,
      "Quantity": 5,
      "Discount": 0.0,
      "SkuCode": "SN78"
    }
  ]
}

What’s cool about RavenDB Studio is that it shows us that the UserId is a reference.

image

RavenDB links the reference up for you as well so you can click it and it will navigate you directly to the document that is being referenced.

There are three ways that we can load this data in code.

  • Roundtrip to the store
  • Include
  • Transform

    Roundtrip to the store

    This method is easy peasy, and it’s pretty similar to something you would do when working with a relational database.

    We do this by calling Load on the Order, then using the value from Order.UserId to load the User.

using (var session = store.OpenSession())
{
    var order = session.Load<Order>("orders/1");
    var user = session.Load<User>(order.UserId);

    Console.WriteLine("Lines: " + order.Lines.Count());
    Console.WriteLine("FirstName: " + user.FirstName);
}

When we run this we get an output like so:

image

The problem with this approach is that we have to go to RavenDB twice, shown here:

image

But it achieves the desired result.

Include

The include method is very similar, the only difference is we tell RavenDB to include the User when we fetch the Order.

This can be done like so:

using (var session = store.OpenSession())
{
    var order = session.Include<Order>(x => x.UserId)
                       .Load<Order>("orders/1");
    var user = session.Load<User>(order.UserId);

    Console.WriteLine("Lines: " + order.Lines.Count());
    Console.WriteLine("FirstName: " + user.FirstName);
}

As you can see all we have done is add the Include method to our initial query.

When we run this we get the exact same output, the difference this time is that RavenDB will issue 1 query for data.

image

So the first query for Order, includes the User. This User object is now part of the current RavenDB Session, so now when we load the User on the next line it doesn’t need to go to RavenDB to fetch it, it already has it.

Transform

This last method is quite different to the last two, it involves writing an index and implementing TransformResults.

First we start by defining an index, which basically just grabs the UserId in the map, then looks up the user in the transform.

public class Order_WithUser : AbstractIndexCreationTask<Order>
{
    public Order_WithUser()
    {
        Map = o => from s in o
                    select new
                    {
                        s.UserId
                    };

        TransformResults = (database, results) =>
            from s in results
            let user = database.Load<User>(s.UserId)
            select new
            {
                s.Id,
                s.UserId,
                s.DateOrdered,
                s.DateUpdated,
                s.Status,
                s.Lines,
                User = user
            };
    }
}

Then we can query it and return it as a new model that includes the User (this could also be added to the Order and not persisted but I’ve made it a separate model for demonstration)

public class OrderResult
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public DateTime DateOrdered { get; set; }
    public DateTime DateUpdated { get; set; }
    public string Status { get; set; }
    public IEnumerable<OrderLine> Lines { get; set; }

    public User User { get; set; }
}
using (var session = store.OpenSession())
{
    var order = session.Query<Order, Order_WithUser>()
        .Where(x => x.Id == "orders/1")
        .AsProjection<OrderResult>()
        .SingleOrDefault();

    Console.WriteLine("Lines: " + order.Lines.Count());
    Console.WriteLine("FirstName: " + order.User.FirstName);
}

When we run this again we get the same results, however in RavenDB we have had to query against an index, rather than just grabbing the document as is.

image


That concludes part 3. Any questions, leave a comment or join the JabbR RavenDB chat room.
Relational database code style Data (computing) Fetch (FTP client) Joins (concurrency library) Testing Session (web analytics) IT POST (HTTP) Links

Published at DZone with permission of Phillip Haydon. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How to Submit a Post to DZone
  • Microservices Discovery With Eureka
  • API Design Patterns Review
  • What Is a Kubernetes CI/CD Pipeline?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: