Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-260

Support dot notation in DBObject.get and DBObject.put

    • Type: Icon: Improvement Improvement
    • Resolution: Won't Fix
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: None
    • Component/s: API
    • Labels:
      None

      While dot notation can be used in queries to look up objects, this is not supported in DBObject.get. Also DBObject.put should handle dots in specified keys accordingly.

      I've written simple static methods that implement the desired behaviour, with related tests.

      Tests first:

          @Test
          public void testGet() {
              assertNull( get( new BasicDBObject( "foo", null ), "foo" ) );
              assertEquals( get( new BasicDBObject( "foo", "bar" ), "foo" ), "bar" );
      
              assertNull( get( new BasicDBObject( "foo", new BasicDBObject( "bar", null ) ), "foo.bar" ) );
              assertEquals( get( new BasicDBObject( "foo", new BasicDBObject( "bar", "baz" ) ), "foo.bar" ), "baz" );
          }
      
          @Test
          public void testPut() {
              BasicDBObject dbo = new BasicDBObject();
              put( dbo, "foo", null );
              assertNull( get( dbo, "foo" ) );
      
              dbo = new BasicDBObject();
              put( dbo, "foo", "bar" );
              assertEquals( get( dbo, "foo" ), "bar" );
      
              dbo = new BasicDBObject();
              put( dbo, "foo.bar", null );
              assertNull( get( dbo, "foo.bar" ) );
      
              dbo = new BasicDBObject();
              put( dbo, "foo.bar", "baz" );
              assertEquals( get( dbo, "foo.bar" ), "baz" );
          }
      

      Implementation of get/put:

          /**
           * Gets the specified property (use dots for specifying an object/property graph) from the given {@link DBObject}.
           * @param <T> the type of the desired result.
           * @param dbo the dbobject.
           * @param key the key or path of keys separated by dots.
           * @return the result or <code>null</code>.
           */
          @CheckForNull
          @SuppressWarnings( "unchecked" )
          public static <T> T get( @Nonnull final DBObject dbo, @Nonnull final String key ) {
              final String[] keys = key.split( "\\." );
              DBObject current = dbo;
              Object result = null;
              for ( int i = 0; i < keys.length; i++ ) {
                  result = current.get( keys[i] );
                  if ( i + 1 < keys.length ) {
                      current = (DBObject) result;
                  }
              }
              return (T) result;
          }
      
          /**
           * Sets the given value for the specified key (or the last key if a property path was
           * specified using dot-notation) on the given {@link DBObject}.
           * @param dbo the dbobject to set the value.
           * @param key the key or path of keys separated by dots.
           * @return the previous value associated with <tt>key</tt>, or
           *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
           *         (A <tt>null</tt> return can also indicate that the map
           *         previously associated <tt>null</tt> with <tt>key</tt>.)
           */
          @CheckForNull
          public static Object put( @Nonnull final DBObject dbo, @Nonnull final String key, @Nullable final Object value ) {
              final String[] keys = key.split( "\\." );
              DBObject current = dbo;
              for ( int i = 0; i + 1 < keys.length; i++ ) {
                  DBObject child = (DBObject) current.get( keys[i] );
                  if ( child == null ) {
                      child = new BasicDBObject();
                      current.put( keys[i], child );
                  }
                  current = child;
              }
              return current.put( keys[keys.length - 1], value );
          }
      

      Could this behaviour be introduced to DBObject implementations or there any reason why this does not make sense?
      If it could be introduces I can implement it in current trunk and provide a patch.

            Assignee:
            Unassigned Unassigned
            Reporter:
            martin.grotzke Martin Grotzke
            Votes:
            10 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: