For example,
it is perfectly valid to have some records where the field "foo" is 123 (integer) and other records where "foo" is "123" (string).
Thus,
you must query for the correct type.
If you save {"foo" => "123"},
you cannot query for it with {"foo" => 123}.
MongoDB is strict about types.

If the type of a field is ambiguous and important to your application,
you should document what you expect the application to send to the database and convert your data to those types before sending.
There are some object-document mappers that will enforce certain types for certain fields for you.

You generally shouldn't save numbers as strings,
as they will behave like strings (e.g.,
range queries won't work correctly) and the data will take up more space.
If you set MongoDB::BSON#looks_like_number,
the driver will automatically convert everything that looks like a number to a number before sending it to the database.

Numbers are the only exception to the strict typing: all number types stored by MongoDB (32-bit integers,
64-bit integers,
64-bit floating point numbers) will match each other.

The Mongo shell has one numeric type: the 8-byte float. This means that it cannot always represent an 8-byte integer exactly. Thus, when you display a 64-bit integer in the shell, it will be wrapped in a subobject that indicates it might be an approximate value. For instance, if we run this Perl on a 64-bit machine:

$coll->insert({_id => 1});

then look at it in the shell, we see:

> db.whatever.findOne()
{
"_id" :
{
"floatApprox" : 1
}
}

This doesn't mean that we saved a float, it just means that the float value of a 64-bit integer may not be exact.

Perl is very flexible about whether something is number or a string: it generally infers the type from context. Unfortunately, the driver doesn't have any context when it has to choose how to serialize a variable. Therefore, the default behavior is to introspect the flags that are set on that variable and decide what the user meant, which are generally affected by the last operation.

This will send anything that "looks like" a number as a number. It can recognize anything that Scalar::Util's looks_like_number function can recognize.

On the other hand, sometimes there is data that looks like a number but should be saved as a string. For example, suppose we were storing zip codes. If we wanted to generally convert strings to numbers, we might have something like:

All strings must be valid UTF-8 to be sent to the database. If a string is not valid, it will not be saved. If you need to save a non-UTF-8 string, you can save it as a binary blob (see the Binary Data section below).

All strings returned from the database have the UTF-8 flag set.

Unfortunately, due to Perl weirdness, UTF-8 is not very pretty. For example, suppose we have a UTF-8 string:

my $str = 'Åland Islands';

Now, let's print it:

print "$str\n";

You can see in the output:

"\x{c5}land Islands"

Lovely, isn't it? This is how Perl prints UTF-8. To make it "pretty," there are a couple options:

my $pretty_str = utf8::encode($str);

This, unintuitively, clears the UTF-8 flag.

You can also just run

binmode STDOUT, ':utf8';

and then the string (and all future UTF-8 strings) will print "correctly."

You can also turn off $MongoDB::BSON::utf_flag_on, and the UTF-8 flag will not be set when strings are decoded:

Warning: creating Perl DateTime objects is extremely slow. Consider saving dates as numbers and converting the numbers to DateTimes when needed. A single DateTime field can make deserialization up to 10 times slower.

For example, you could use the time function to store seconds since the epoch:

"OID" stands for "Object ID", and is a unique id that is automatically added to documents if they do not already have an _id field before they are saved to the database. They are 12 bytes which are guarenteed to be unique. Their string form is a 24-character string of hexidecimal digits.

To create a unique id:

my $oid = MongoDB::OID->new;

To create a MongoDB::OID from an existing 24-character hexidecimal string:

You can also use the MongoDB::BSON::Binary class. This allows you to preserve the subtype of your data. Binary data in MongoDB stores a "type" field, which can be any integer between 0 and 255. Identical data will only match if the subtype is the same.

Perl uses the default subtype of SUBTYPE_GENERIC.

The driver defaults to returning binary data as strings, not instances of MongoDB::BSON::Binary (or even string references) for backwards compatibility reasons. If you need to round-trip binary data, set the MongoDB::BSON::use_binary flag:

$MongoDB::BSON::use_binary = 1;

Comparisons (e.g., $gt, $lt) may not work as you expect with binary data, so it is worth experimenting.