<commit_before>********
Tutorial
********

.. py:currentmodule:: happybase

This tutorial explores the HappyBase API and should provide you with enough
information to get you started. Note that this tutorial is intended as an
introduction to HappyBase, not to HBase in general. Readers should already have
a basic understanding of HBase and its data model.

While the tutorial does cover most features, it is not a complete reference
guide. More information about the HappyBase API is available from the :doc:`API
documentation <api>`.

.. contents:: On this page
   :local:


Opening a :py:class:`Connection`
================================

We'll get started by connecting to HBase::

   import happybase

   connection = happybase.Connection('somehost')

When a :py:class:`Connection` instance is created, it automatically opens a
socket connection to the HBase Thrift server. This behaviour can be disabled by
setting the `autoconnect` argument to `False`, and opening the connection
manually using :py:meth:`Connection.open`::

   connection = happybase.Connection('somehost', autoconnect=False)

   # before first use:
   connection.open()

The :py:class:`Connection` class provides various methods to interact with the
HBase instance. For instance, we can ask ask for the names of the available
tables using the :py:meth:`Connection.tables` method::

   print connection.tables()

If a single HBase instance is used by multiple applications, table name
collisions may occur because applications use the same table names. A solution
is to add a ‘namespace’ prefix to the names of all tables ‘owned’ by a specific
application. Instead of adding this application-specific prefix each time a
table name is passed to HappyBase, the `table_prefix` parameter can be used.
HappyBase will prepend that prefix (and an underscore) to each table name
handled by the :py:class:`Connection` instance. So, for a project ``myproject``
that should have table names that look like ``myproject_XYZ``, use this::

   connection = happybase.Connection('somehost', table_prefix='myproject')

:py:meth:`Connection.tables` no longer includes tables in other ‘namespaces’;
it will only returns tables with a ``myproject_`` prefix in HBase, and also
strips of the prefix::

   print connection.tables()  # Table "myproject_XYZ" in HBase will be
                              # returned as simply "XYZ"

The :py:class:`Connection` class offers various other methods to interact with
HBase, mostly to perform table management tasks like enabling and disabling
tables. This tutorial does not cover those; the :doc:`API documentation <api>`
for the :py:class:`Connection` class contains more information.


Obtaining a :py:class:`Table` instance
======================================

The :py:class:`Table` class provides the main API to retrieve and manipulate
data in HBase. In the example above, we already asked for the available tables
using the :py:meth:`Connection.tables` method, so the next step is to obtain a
:py:class:`.Table` instance. This is done by calling
:py:meth:`Connection.table` with the name of the table::

   table = connection.table('mytable')

Obtaining a :py:class:`Table` instance does *not* result in a round-trip to the
Thrift server, which means application code may ask the :py:class:`Connection`
instance for a new :py:class:`Table` whenever it needs one, without negative
performance consequences. A side effect is that no check is done to ensure that
the table exists, since that would involve a round-trip, so expect errors if
you try to interact with non-existing tables later in your code. For this
tutorial, we assume the table exists.

.. note::

   The ‘heavy’ `HTable` HBase class from the Java HBase API, which does the
   real communication with the region servers, is at the other side of the
   Thrift connection. There is no direct mapping between :py:class:`Table`
   instances on the Python side and `HTable` instances on the server side.


Retrieving data
===============

The HBase data model is a multidimensional sparse map. A table in HBase
contains column families with column qualifiers containing a value and a
timestamp. In most of the HappyBase API, column family and qualifier names are
specified as a single string, e.g. ``cf1:col1``, and not as two separate
arguments. While column families and qualifiers are different concepts in the
HBase data model, they are almost always used together when interacting with
data, so treating them as a single string makes the API a lot simpler.

Retrieving rows
---------------

The :py:class:`Table` class offers various methods to retrieve data from a
table in HBase. The most basic one is :py:meth:`Table.row`, which retrieves a
single row from the table, and returns it as a dictionary mapping columns to
values::

   row = table.row('row-key')
   print row['cf1:col1']   # prints the value of cf1:col1

The :py:meth:`Table.rows` method works just like :py:meth:`Table.row`, but
takes multiple row keys and returns those as `(key, data)` tuples::<commit_msg>Some tutorial cleanups<commit_after>********
Tutorial
********

.. py:currentmodule:: happybase

This tutorial explores the HappyBase API and should provide you with enough
information to get you started. Note that this tutorial is intended as an
introduction to HappyBase, not to HBase in general. Readers should already have
a basic understanding of HBase and its data model.

While the tutorial does cover most features, it is not a complete reference
guide. More information about the HappyBase API is available from the :doc:`API
documentation <api>`.

.. contents:: On this page
   :local:


Opening a connection
====================

We'll get started by connecting to HBase::

   import happybase

   connection = happybase.Connection('somehost')

When a :py:class:`Connection` instance is created, it automatically opens a
socket connection to the HBase Thrift server. This behaviour can be disabled by
setting the `autoconnect` argument to `False`, and opening the connection
manually using :py:meth:`Connection.open`::

   connection = happybase.Connection('somehost', autoconnect=False)

   # before first use:
   connection.open()

The :py:class:`Connection` class provides various methods to interact with the
HBase instance. For instance, we can ask ask for the names of the available
tables using the :py:meth:`Connection.tables` method::

   print connection.tables()

The :py:class:`Connection` class offers various other methods to interact with
HBase, mostly to perform table management tasks like enabling and disabling
tables. This tutorial does not cover those; the :doc:`API documentation <api>`
for the :py:class:`Connection` class contains more information.

Using a table name prefix
-------------------------

If a single HBase instance is used by multiple applications, table name
collisions may occur because applications use the same table names. A solution
is to add a ‘namespace’ prefix to the names of all tables ‘owned’ by a specific
application. Instead of adding this application-specific prefix each time a
table name is passed to HappyBase, the `table_prefix` parameter can be used.
HappyBase will prepend that prefix (and an underscore) to each table name
handled by the :py:class:`Connection` instance. So, for a project ``myproject``
that should have table names that look like ``myproject_XYZ``, use this::

   connection = happybase.Connection('somehost', table_prefix='myproject')

At this point, :py:meth:`Connection.tables` no longer includes tables in other
‘namespaces’; it will only returns tables with a ``myproject_`` prefix in
HBase, and also strips of the prefix::

   print connection.tables()  # Table "myproject_XYZ" in HBase will be
                              # returned as simply "XYZ"


Working with tables
===================

The :py:class:`Table` class provides the main API to retrieve and manipulate
data in HBase. In the example above, we already asked for the available tables
using the :py:meth:`Connection.tables` method. The next step is to obtain a
:py:class:`.Table` instance to work with. Obtain a table by calling
:py:meth:`Connection.table`, passing it the table name::

   table = connection.table('mytable')

Obtaining a :py:class:`Table` instance does *not* result in a round-trip to the
Thrift server, which means application code may ask the :py:class:`Connection`
instance for a new :py:class:`Table` whenever it needs one, without negative
performance consequences. A side effect is that no check is done to ensure that
the table exists, since that would involve a round-trip. Expect errors if you
try to interact with non-existing tables later in your code. For this tutorial,
we assume the table exists.

.. note::

   The ‘heavy’ `HTable` HBase class from the Java HBase API, which performs the
   real communication with the region servers, is at the other side of the
   Thrift connection. There is no direct mapping between :py:class:`Table`
   instances on the Python side and `HTable` instances on the server side.


Retrieving data
===============

The HBase data model is a multidimensional sparse map. A table in HBase
contains column families with column qualifiers containing a value and a
timestamp. In most of the HappyBase API, column family and qualifier names are
specified as a single string, e.g. ``cf1:col1``, and not as two separate
arguments. While column families and qualifiers are different concepts in the
HBase data model, they are almost always used together when interacting with
data, so treating them as a single string makes the API a lot simpler.

Retrieving rows
---------------

The :py:class:`Table` class offers various methods to retrieve data from a
table in HBase. The most basic one is :py:meth:`Table.row`, which retrieves a
single row from the table, and returns it as a dictionary mapping columns to
values::

   row = table.row('row-key')
   print row['cf1:col1']   # prints the value of cf1:col1

The :py:meth:`Table.rows` method works just like :py:meth:`Table.row`, but
takes multiple row keys and returns those as `(key, data)` tuples::
{'fraction_non_alphanumeric': 0.08720585327269131, 'fraction_numerical': 0.0011864741941862765, 'mean_word_length': 4.597675705589374, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3660203', 'n_tokens_mistral': 2601, 'n_tokens_neox': 2516, 'n_words': 1376}