Skip to content

Inverted Relation Retrieval

Backendless supports a special query syntax for loading a subset of child objects for a specific parent. Consider the following table schemas:

PhoneBook table:

phonebook-table-schema

Contact table:

contact-table-schema

Address table:

address-table-schema

These tables will be used to demonstrate how to query Backendless for conditional related object retrieval.

The Map-based approach does not require you defining classes for the objects stored in Backendless. Instead your code can use java.util.Map to to store and retrieve objects in/from Backendless. === "Custom Class"

Consider the following class definitions for the entities from the diagram: PhoneBook class:

package com.sample.entity;

import java.util.List;

public class PhoneBook
{
  private String objectId;
  private Contact owner;
  private List<Contact> contacts;

  public String getObjectId()
  {
    return objectId;
  }

  public void setObjectId( String objectId )
  {
    this.objectId = objectId;
  }

  public Contact getOwner()
  {
    return owner;
  }

  public void setOwner( Contact owner )
  {
    this.owner = owner;
  }

  public List<Contact> getContacts()
  {
    return contacts;
  }

  public void setContacts( List<Contact> contacts )
  {
    this.contacts = contacts;
  }
}
Contact class:
package com.sample.entity;

import java.util.Date;

public class Contact
{
  private String objectId;
  private String name;
  private int age;
  private String phone;
  private String title;
  private Address address;
  private Date updated;

  public String getObjectId()
  {
    return objectId;
  }

  public void setObjectId( String objectId )
  {
    this.objectId = objectId;
  }

  public String getName()
  {
    return name;
  }

  public void setName( String name )
  {
    this.name = name;
  }

  public int getAge()
  {
    return age;
  }

  public void setAge( int age )
  {
    this.age = age;
  }

  public String getPhone()
  {
    return phone;
  }

  public void setPhone( String phone )
  {
    this.phone = phone;
  }

  public String getTitle()
  {
    return title;
  }

  public void setTitle( String title )
  {
    this.title = title;
  }

  public Address getAddress()
  {
    return address;
  }

  public void setAddress( Address address )
  {
    this.address = address;
  }

  public Date getUpdated()
  {
    return updated;
  }

  public void setUpdated( Date updated )
  {
    this.updated = updated;
  }
}
Address class:
package com.sample.entity;

public class Address
{
  private String street;
  private String city;
  private String state;

  public String getStreet()
  {
    return street;
  }

  public void setStreet( String street )
  {
    this.street = street;
  }

  public String getCity()
  {
    return city;
  }

  public void setCity( String city )
  {
    this.city = city;
  }

  public String getState()
  {
    return state;
  }

  public void setState( String state )
  {
    this.state = state;
  }
}

The general structure of a whereClause query to load a collection of child objects for a specific parent object is:

ParentTableName[ relatedColumnName ].parentColumnName COLUMN-VALUE-CONDITION

Both columns relatedColumnName and parentColumnName must be declared in a table with name of ParentTableName. The relatedColumnName must be a relation column. The table relatedColumnName points to is the table where the objects must be loaded from.  The examples below demonstrate the usage of this syntax:

Find all contacts in a city for a specific phone book

StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.get( "objectId" ).append( "'" );
whereClause.append( " and " );
whereClause.append( "address.city = 'Smallville'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Map> result = Backendless.Data.of( "Contact" ).find( queryBuilder );
StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.getObjectId() ).append( "'" );
whereClause.append( " and " );
whereClause.append( "address.city = 'Smallville'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Contact> result = Backendless.Data.of( Contact.class ).find( queryBuilder );

Codeless Reference

The following example is identical to the one presented above and uses the following condition in thewhere clause property: This operation is set to retrieve related objects whose city is 'New York'.

PhoneBook[contacts].objectId = 'DB7A04FD-C305-4615-8480-BF75F244F10F' and address.city = 'New York'

data_inverted_relation_retrieval

Important

For a detailed description of all input parameters see the Basic Object Retrieval topic of this guide.

After the Codeless logic runs, the operation returns two objects whose city is 'New York'.

data_inverted_relation_retrieval_2


Find all contacts for the specific phone book where the city name contains letter 'a'

StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.get( "objectId" ) ).append( "'" );
whereClause.append( " and " );
whereClause.append( "address.city like '%a%'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Map> result = Backendless.Data.of( "Contact" ).find( queryBuilder );
StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.getObjectId() ).append( "'" );
whereClause.append( " and " );
whereClause.append( "address.city like '%a%'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Contact> result = Backendless.Data.of( Contact.class ).find( queryBuilder );

Codeless Reference

The following example is identical to the one presented above and uses the following condition in thewhere clause property. This operation is set to retrieve related objects whose name of the city contains at least one letter 'a'.

PhoneBook[contacts].objectId = 'DB7A04FD-C305-4615-8480-BF75F244F10F' and address.city like '%a%'

data_inverted_relation_retrieval

After the Codeless logic runs, the operation returns four objects that have at least one letter 'a' in the name of the city.

data_inverted_relation_retrieval_3


Find all contacts where age is greater than 20 for a specific phone book

StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.get( "objectId" ) ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age > 20" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Map> result = Backendless.Data.of( "Contact" ).find( queryBuilder );
StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.getObjectId() ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age > 20" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Contact> result = Backendless.Data.of( Contact.class ).find( queryBuilder );

Codeless Reference

The following example is identical to the one presented above and uses the following condition in thewhere clause property: This operation is set to retrieve related objects whose age is greater than 20.

PhoneBook[contacts].objectId = 'DB7A04FD-C305-4615-8480-BF75F244F10F' and age > 20

data_inverted_relation_retrieval

After the Codeless logic runs, the operation returns four objects that match the where clause condition. As you can see, the value in the age property is greater than 20.

data_inverted_relation_retrieval_4


Find all contacts for a specific phone book where age is within the specified range

StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.get( "objectId" ) ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age >= 21 and age <= 30" )

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Map> result = Backendless.Data.of( "Contact" ).find( queryBuilder );
StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.getObjectId() ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age >= 21 and age <= 30" )

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Contact> result = Backendless.Data.of( Contact.class ).find( queryBuilder );

Codeless Reference

The following example is identical to the one presented above and uses the following condition in thewhere clause property: This operation is set to retrieve related objects using the age properties whose values are in range between 21 and 30 .

PhoneBook[contacts].objectId = 'DB7A04FD-C305-4615-8480-BF75F244F10F' and age >= 21 and age <= 30

data_inverted_relation_retrieval

After the Codeless logic runs, the operation returns only one object since it matches the where clause condition.

data_inverted_relation_retrieval_5


Find all contacts for a specific phone book where age is greater than 20 and the city is Tokyo

StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.get( "objectId" ) ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age > 20 and address.city = 'Tokyo'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Map> result = Backendless.Data.of( "Contact" ).find( queryBuilder );
StringBuilder whereClause = new StringBuilder();
whereClause.append( "PhoneBook[contacts]" );
whereClause.append( ".objectId='" ).append( savedPhoneBook.getObjectId() ).append( "'" );
whereClause.append( " and " );
whereClause.append( "age > 20 and address.city = 'Tokyo'" );

DataQueryBuilder queryBuilder = DataQueryBuilder.create();
queryBuilder.setWhereClause( whereClause.toString() );
List<Contact> result = Backendless.Data.of( Contact.class ).find( queryBuilder );

Codeless Reference

The following example is identical to the one presented above and uses the following condition in thewhere clause property: This operation is set to retrieve related objects using the age properties whose values is greater than 21, and also the city properties whose value is 'Tokyo'.

PhoneBook[contacts].objectId = 'DB7A04FD-C305-4615-8480-BF75F244F10F' and age > 21 and address.city = 'Tokyo'

data_inverted_relation_retrieval

After the Codeless logic runs, the operation returns only one object matching the where clause condition.

data_inverted_relation_retrieval_6