Reader small image

You're reading from  RavenDB 2.x Beginner's Guide

Product typeBook
Published inSep 2013
PublisherPackt
ISBN-139781783283798
Edition1st Edition
Right arrow
Author (1)
Khaled Tannir
Khaled Tannir
author image
Khaled Tannir

Khaled Tannir has been working with computers since 1980. He began programming with the legendary Sinclair Zx81 and later with Commodore home computer products (Vic 20, Commodore 64, Commodore 128D, and Amiga 500). He has a Bachelor's degree in Electronics, a Master's degree in System Information Architectures, in which he graduated with a professional thesis, and completed his education with a Master of Research degree. He is a Microsoft Certified Solution Developer (MCSD) and has more than 20 years of technical experience leading the development and implementation of software solutions and giving technical presentations. He now works as an independent IT consultant and has worked as an infrastructure engineer, senior developer, and enterprise/solution architect for many companies in France and Canada. With significant experience in Microsoft .Net, Microsoft Server Systems, and Oracle Java technologies, he has extensive skills in online/offline applications design, system conversions, and multilingual applications in both domains: Internet and Desktops. He is always researching new technologies, learning about them, and looking for new adventures in France, North America, and the Middle-east. He owns an IT and electronics laboratory with many servers, monitors, open electronic boards such as Arduino, Netduino, RaspBerry Pi, and .Net Gadgeteer, and some smartphone devices based on Windows Phone, Android, and iOS operating systems. In 2012, he contributed to the EGC 2012 (International Complex Data Mining forum at Bordeaux University, France) and presented, in a workshop session, his work on "how to optimize data distribution in a cloud computing environment". This work aims to define an approach to optimize the use of data mining algorithms such as k-means and Apriori in a cloud computing environment. He is the author of RavenDB 2.x Beginner's Guide, Packt Publishing. He aims to get a PhD in Cloud Computing and Big Data and wants to learn more and more about these technologies. He enjoys taking landscape and night time photos, travelling, playing video games, creating funny electronic gadgets with Arduino/.Net Gadgeteer, and of course, spending time with his wife and family. You can reach him at contact@khaledtannir.net.
Read more about Khaled Tannir

Right arrow

Chapter 5. Advanced RavenDB Indexes and Queries

Advanced queries allow you to execute more complex query statements in RavenDB. In this chapter, you will learn a different way to create indexes by inheriting from the AbstractIndexCreatingTask class.

We will cover Multi map indexes and learn how to create them. Also you will learn how to register fields to be indexed, how to combine searching option, paging a query result, and some other useful techniques to improve the runtime performance of your queries.

In this chapter, we will cover:

  • Creating indexes using the AbstractIndexCreatingTask class

  • Multi map indexes

  • Full text and exact match searching indexes

  • Paging query results

The RavenDB AbstractIndexCreationTask class


RavenDB has a lot features to create indexes. In the previous chapter, we learned how to create an index and define its Map and Reduce functions using the PutIndex() method and the IndexDefinitionBuilder class. But there is a better way to do this by using the AbstractIndexCreationTask class and using the CreateIndex() method to submit the index to the server.

The AbstractIndexCreationTask class is an abstract generic class. That means no object of this class can be instantiated, but can only make derivations of this class. Also as it is a generic class, it requires the document type to be specified and optionally a ReduceResult type class.

Querying the RavenDB indexes created using the AbstractIndexCreationTask class is the same as the indexes created using the PutIndex() method. You can either let RavenDB decide which index to use, or instruct it to use a specific index by explicitly specifying the index name while querying.

Creating indexes using the AbstractIndexCreationTask class


It is very easy to create indexes using the AbstractIndexCreationTask class. Basically, you will create a new class for the index that will inherit from the AbstractIndexCreationTask class and define the document object type. The index you will create requires at least one map function to be defined. You can define this function in the class constructor directly instead of creating a new instance of the IndexDefinitionBuilder class as we did while using the PutIndex() method.

Time for action – creating indexes using AbstractIndexCreationTask class


Let's take a look and learn how to create a new index by inheriting from the AbstractIndexCreationTask class. To create the index we will create a new project and add a new class that inherits from this class. The index definition is very easy and will contain only one Map function that retrieves the CountryId key. To get all cities in the USA, we will query the index and filter the result. Once the index is created you will execute it in Management Studio and view the result.

  1. Start Visual Studio, create a new project and name it RavenDB_CH05.

  2. Use the NuGet Package Manager to add a reference to the RavenDB Client.

    Note

    We need to use the City and Country classes created in the previous chapter, you may make a copy into this project or create a new one.

  3. Add a new class to the project, name it City and complete it with the following code snippet:

  4. Add a new class to the project, name it Country and complete it with the following...

Time for action – creating indexes using the ResultReduce class


We will create a new index which will aggregate the World database to make a count of Cities that have the same name in different countries and return the CountryId key for each city as a single document. The following screenshot illustrates the expected result:

  1. Start Visual Studio and open the RavenDB_CH05 solution.

  2. Add a new class to the project, name it Cities_SameName and add the following code snippet:

    Tip

    We named the embedded class ReduceResult by convention. You can choose any other name for this class and place it outside the index class.

    We could use a String type in the ReduceResult class to store the document ID CountriesId (which is a string type), but we choose to create a second embedded class, for learning purposes and show that it is possible to create more complex structure.

  3. Add a default constructor to the Cities_SameName class and within this constructor add the index Map function using the following code snippet...

Time for action – using the TransformResults function


You will create a new index class, then add a Map and TransformResults function. The index definition will contain only one Map function that retrieves the city population. Once the index is created you will execute it in Management Studio and view the result.

  1. Open the RavenDB_CH05 project in Visual Studio.

  2. Add a new class, name it TransformationResult and complete it with the following code snippet:

  3. Add a new class, and name it Cities_ByPopulation and complete it with the following code snippet:

  4. Add the following code snippet to the Main() method in the Program class:

  5. Save all the files, build and run the solution.

  6. In Management Studio, execute the Cities/ByPopulation index and observe the result.

What just happened?

You just created the Cities_ByPopulation index and implemented its Map function and TransformResults functions in order to transform the Map function result and get something different from the original Map result.

We begin by...

Creating multimap indexes


RavenDB allows you to define more than one Map function for static indexes. In this case such indexes are called Multi map indexes. When using a Multi map index, we are looking to take information from different documents. A single map index has only one Map function, while a Multi map index has more than one Map function. A Multi map index will get its data from multiple sources. It may have no or only one Reduce function, and no or only one TranformResults function.

If the index has a Reduce function, then the multi map(s) function(s) output is sent to the Reduce function. The only requirement that we have is that the output of all of the Map functions should be identical (and obviously, matches the output of the Reduce function). Then we can just treat this information as normal Map/Reduce index, which means that you can use all usual index features of RavenDB.

To create a multi map index class, we have to inherit from the AbstractMultiMapIndexCreationTask class...

Time for action – creating multimap indexes


We will create a new index class that aggregates the World database and makes a count of Cities in each country using a multi map index.

  1. Start Visual Studio and open the RavenDB_CH05 solution.

  2. Add a new class to the project, name it Cities_MMapCitiesByCountry and add the following code snippet:

  3. Add a default constructor to the Cities_MMCitiesByCountry class and within this constructor add two Map functions using the following code snippet:

  4. Within the Cities_MMCitiesByCountry class constructor add the index Reduce function using the following code snippet:

  5. Modify the Main method in the Program class using the following code snippet.

  6. Save all files, build and run the solution.

  7. In Management Studio, execute the Cities/MMCitiesByCountry index.

What just happened?

You just created the multi map Cities_MMCitiesByCountry index class. This index aims to aggregate the World database and get the cities count in each country.

The Cities_MMCitiesByCountry class inherits...

Time for action – creating a full-text searching index


We will create a new full-text index searching class using a single search term. This index will search matching text over the Cities collection based on the city name field value.

  1. Start Visual Studio and open the RavenDB_CH5 solution.

  2. Add a new class to the project, name it Cities_FullTextSearch and add the following code snippet:

  3. Modify the Main() method in the Program class using the following code snippet:

    Note

    The Contains() method is not supported, performing a substring match over a text field is a very slow operation, and is not allowed using the LINQ API. The recommended method is to use the .Search() method to query it. (The field has to be marked as Analyzed).

  4. Save all the files, build and run the solution.

What just happened?

You created the Cities_FullTextSearch index class to allow single term full-text searching over the city.Name text field.

The Cities_FullTextSearch class inherits from the AbstractIndexCreationTask class and...

Time for action – creating multifields searching index


You will create a new index class and register three fields to be indexed. This index will perform search over the Cities and Countries collections. To query this index you will use consecutive .Search() method and specify SearchOptions for each method.

  1. Start Visual Studio and open the RavenDB_CH05 solution.

  2. Add a new class to the project, name it Cities_MultiFieldsSearch and it inherits from AbstractIndexCreationTask class:

  3. Add a default constructor, and then add the Map function within the class constructor using the following code snippet:

  4. Add Indexes field's registration to the class constructor using the following code snippet:

  5. Add the following code snippet to the Main() method in the Program class:

  6. Save all the files, build and run the solution.

What just happened?

You created the Cities_MutliFieldsSearch() index class to search over multiple indexed fields.

This index will define one Map function that inherits from the AbstractIndexCreationTask...

Time for action – using a custom analyzer


You will create a new index class and register one field that will use a specific analyzer, the FrenchAnalyzer. This index will perform search over the Cities collections on the Name field. To query this index you will use a .Search() method and specify a Where closure.

  1. Start Visual Studio and open the RavenDB_CH05 solution.

  2. Use the NuGet Package Manager to add a reference to the Lucen.Net Contrib package:

  3. Add a new class to the project, name it Cities_CustomAnalyzer that inherits from AbstractIndexCreationTask class:

  4. Add a default constructor, and then add the Map function within the class constructor using the following code snippet:

  5. Under the Map function, add Analyzer field's registration to the class constructor using the following code snippet:

  6. Add the following code snippet to the Main() method in the Program class:

  7. Save all the files.

  8. Open the RavenDB_Ch05 output folder and copy Lucene.Net.Contrib.Analyzers.dll to the \Analyzers folder under the...

Paging a query's results


Paging a query result is the process of returning the results of a query in smaller subsets of data, or pages. Nowadays implementing pagination is a very common scenario for displaying results to a user in small, easy to manage chunks.

RavenDB allows query's result pagination and supports both Skip and Take LINQ operators, making paging through a collection easy. To perform paging you will call the Take and Skip operators on the Query object to return a given number of elements and/or to skip over a given number of elements and then return the remainder.

As RavenDB is safe by default, it protects itself and user applications from overload scenarios and limits the number of documents to be returned to the client from the server. In large dataset scenarios it makes paging mandatory. This means that we need to ensure that we limit the result sets to reasonable sizes.

By default, the number of documents on the client side is 128 (but you can change that) and 1024 for the...

Time for action – paging a query's results


Now let's take a look at how to implement paging in RavenDB. You will add two new methods to the Program class: the first one will query the Countries collection using Skip() and Take() methods, the second one will display the query's result pages.

  1. Start Visual Studio and open the RavenDB_Ch05 solution.

  2. Add the following code to the Main() method in the Program class:

  3. Save all the files, build and run the solution.

What just happened?

We just queried the Countries Collection and implemented paging on the query result. By design RavenDB limits the number of returned documents to the client to 128 no matter how many there actually are.

In the code snippet (line 121), we declare a RavenQueryStatistics field to hold the output of the Statistics extension method, which will allow you to read the number of TotalResults.

While the only thing we wanted to do is to get the document count. So making Take(0) call will explicitly tell RavenDB not to load any entities...

Summary


In this chapter, we learned some advanced techniques to execute more complex query statements in RavenDB, which will help us to use RavenDB in an efficient way. Specifically we covered how to create indexes using the AbstractIndexCreatingTask class, what are multi map indexes and how to create them.

Also we learned how to register fields to be indexed and how to combine searching options.

Then we presented paging and how to page query's results using Skip() and Take() LINQ operators to return small data chunks to the user.

In the next chapter, we will talk about RavenDB documents attachment, about handling documents relationships and some useful techniques to patch a single document or a set of documents using a JavaScript. So let's go!

lock icon
The rest of the chapter is locked
You have been reading a chapter from
RavenDB 2.x Beginner's Guide
Published in: Sep 2013Publisher: PacktISBN-13: 9781783283798
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Khaled Tannir

Khaled Tannir has been working with computers since 1980. He began programming with the legendary Sinclair Zx81 and later with Commodore home computer products (Vic 20, Commodore 64, Commodore 128D, and Amiga 500). He has a Bachelor's degree in Electronics, a Master's degree in System Information Architectures, in which he graduated with a professional thesis, and completed his education with a Master of Research degree. He is a Microsoft Certified Solution Developer (MCSD) and has more than 20 years of technical experience leading the development and implementation of software solutions and giving technical presentations. He now works as an independent IT consultant and has worked as an infrastructure engineer, senior developer, and enterprise/solution architect for many companies in France and Canada. With significant experience in Microsoft .Net, Microsoft Server Systems, and Oracle Java technologies, he has extensive skills in online/offline applications design, system conversions, and multilingual applications in both domains: Internet and Desktops. He is always researching new technologies, learning about them, and looking for new adventures in France, North America, and the Middle-east. He owns an IT and electronics laboratory with many servers, monitors, open electronic boards such as Arduino, Netduino, RaspBerry Pi, and .Net Gadgeteer, and some smartphone devices based on Windows Phone, Android, and iOS operating systems. In 2012, he contributed to the EGC 2012 (International Complex Data Mining forum at Bordeaux University, France) and presented, in a workshop session, his work on "how to optimize data distribution in a cloud computing environment". This work aims to define an approach to optimize the use of data mining algorithms such as k-means and Apriori in a cloud computing environment. He is the author of RavenDB 2.x Beginner's Guide, Packt Publishing. He aims to get a PhD in Cloud Computing and Big Data and wants to learn more and more about these technologies. He enjoys taking landscape and night time photos, travelling, playing video games, creating funny electronic gadgets with Arduino/.Net Gadgeteer, and of course, spending time with his wife and family. You can reach him at contact@khaledtannir.net.
Read more about Khaled Tannir