RejectedSoftware Forums

Sign up

MongoDB Checking for existence of a field

I have a mongo collection that holds documents which may or may
not contain various fields. I'm trying to determine the correct
way to check for a field. Right now all I have been able to come
up with is trying to deserialize (Bson) or get (Json) the field
and catch the exception that occurs when it isn't valid.

I've tried comparing the type to Json.Type.Undefined but that's
not working for some reason.

What's the right way to check for the existence of a field in a
Mongo document?

Re: MongoDB Checking for existence of a field

Am 15.07.2012 21:11, schrieb David Eagen:

I have a mongo collection that holds documents which may or may not
contain various fields. I'm trying to determine the correct way to check
for a field. Right now all I have been able to come up with is trying to
deserialize (Bson) or get (Json) the field and catch the exception that
occurs when it isn't valid.

I've tried comparing the type to Json.Type.Undefined but that's not
working for some reason.

What's the right way to check for the existence of a field in a Mongo
document?

According to the BSON spec Undefined is deprecated. For that reason
Type.Null is returned instead, so bson.isNull() or bson.type ==
Bson.Type.Null should work.

Alternatively you can also use bson.myfield.opt!int(-1) != -1 to test
for an integer field "myfield" and get its value at the same time.

Re: MongoDB Checking for existence of a field

On Sunday, 15 July 2012 at 19:36:50 UTC, Sönke Ludwig wrote:

According to the BSON spec Undefined is deprecated. For that
reason Type.Null is returned instead, so bson.isNull() or
bson.type == Bson.Type.Null should work.

Alternatively you can also use bson.myfield.opt!int(-1) != -1
to test for an integer field "myfield" and get its value at the
same time.

Looks like isNull() isn't working, at least not from my diet
page. In the data it is processing the first three entries
contain the field but the fourth does not which generates the
error.

  • auto endVerseBson = bsonDoc["endVerse"];
  • if(!endVerseBson.isNull())
  • {
  • import std.stdio;
  • writeln("Type for endVerse is ", endVerseBson.type);
  • float endVerse;
  • deserializeBson!float(endVerse, endVerseBson);
  • formattedWrite(referenceAppender, "-%0g", endVerse);
  • }

When run yields:

Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Null
[7F17E05F6017:7F17E05F4317 ERR] Error after page has been
written: BSON value is type 'Null', expected to be one of [Double]

So, the isNull passes but the type is actuall Null.

Replacing the if test with this also doesn't work:

  • if(endVerseBson.type != Bson.Type.Null)

When run it yields:

Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Null
[7F0B1E12D00B:7F0B1E12B30B ERR] Error after page has been
written: BSON value is type 'Null', expected to be one of [Double]

Re: MongoDB Checking for existence of a field

On Sunday, 15 July 2012 at 22:42:03 UTC, David Eagen wrote:

Looks like isNull() isn't working, at least not from my diet
page. In the data it is processing the first three entries
contain the field but the fourth does not which generates the
error.

  • auto endVerseBson = bsonDoc["endVerse"];
  • if(!endVerseBson.isNull())
  • {
  • import std.stdio;
  • writeln("Type for endVerse is ", endVerseBson.type);
  • float endVerse;
  • deserializeBson!float(endVerse, endVerseBson);
  • formattedWrite(referenceAppender, "-%0g", endVerse);
  • }

When run yields:

Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Double
Type for endVerse is Null
[7F17E05F6017:7F17E05F4317 ERR] Error after page has been
written: BSON value is type 'Null', expected to be one of
[Double]

It's getting even stranger. I added logging of the result of
isNull() to the if statement:

  • auto endVerseBson = bsonDoc["endVerse"];
  • if(!(endVerseBson.isNull()))
  • {
  • import std.stdio;
  • writeln("endVerseBson isNull() => ", endVerseBson.isNull());
  • writeln("Type for endVerseBson is ", endVerseBson.type);
    ...

endVerseBson isNull() => false
Type for endVerseBson is Double
endVerseBson isNull() => false
Type for endVerseBson is Double
endVerseBson isNull() => false
Type for endVerseBson is Double
endVerseBson isNull() => true
Type for endVerseBson is Null
[7FAC5427F0AC:7FAC5427D3AC ERR] Error after page has been
written: BSON value is type 'Null', expected to be one of [Double]

So, isNull is correctly true inside the if but incorrectly false
when testing for the if condition.

Since I'm doing this inside a Diet template I thought maybe there
was something bugged there so I tried using isNull in a regular D
function. It works correctly there. So this problem appears to be
only occurring when using Diet.

I'm using the latest version of Vibe.d from git (pulled today
just after the 0.7.6 release) and DMD 2.059 on Linux 64-bit.

Re: MongoDB Checking for existence of a field

Filed an issue for this. I tried using isNaN() inside the if and
found the same behavior there.

https://github.com/rejectedsoftware/vibe.d/issues/75

Re: MongoDB Checking for existence of a field

(Just rehashing here from github for reference)

The problem here is that D statements (i.e. lines starting with '-')
also have to be nested using indentation and not using the usual braces.
So the example would become:

  • auto endVerseBson = bsonDoc["endVerse"];
  • if(!endVerseBson.isNull())
    • import std.stdio;
    • writeln("Type for endVerse is ", endVerseBson.type);
    • float endVerse;
    • deserializeBson!float(endVerse, endVerseBson);
    • formattedWrite(referenceAppender, "-%0g", endVerse);

I've added now an explicit statement in the template docs about this
and, additionally, the parser will now error out as soon as it detects a
'{' at the end of a line, telling to use indentation.