-
Type: Improvement
-
Resolution: Won't Fix
-
Priority: Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: API
-
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.
- is duplicated by
-
JAVA-2532 Improve the Document class in Java to allow referencing of embedded documents using the dot notation.
- Closed