Merge pull request #1746 from realm/jas/backlink-update
Initial work for unnamed backlink queries and backlink count
This commit is contained in:
commit
0c73b06ce4
|
@ -95,3 +95,21 @@ Example:
|
||||||
// Find contacts with friends above 21 in SF
|
// Find contacts with friends above 21 in SF
|
||||||
let teens = realm.objects('Contact').filtered('SUBQUERY(friends, $friend, $friend.age > 21 AND $friend.city = "SF").@count > 0');
|
let teens = realm.objects('Contact').filtered('SUBQUERY(friends, $friend, $friend.age > 21 AND $friend.city = "SF").@count > 0');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Backlink queries
|
||||||
|
|
||||||
|
Other objects can link to an object and you can query on that releationship using the `@links` and `@links.ClassName.PropertyName` syntax.
|
||||||
|
If the relationship of the LinkingObject is named, use the name in the query just like you would use any other property for readability.
|
||||||
|
If the relationship is not named, you can use the `@links.ClassName.PropertyName` syntax where `ClassName.PropertyName` describes the forward relationship.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```JS
|
||||||
|
// Find contacts where someone from SF has them as friends
|
||||||
|
realm.objects('Contact').filtered('@links.Contact.friends.city == "SF"');
|
||||||
|
|
||||||
|
// Find contacts with no incomming links (across all linked properties)
|
||||||
|
let isolated = realm.objects('Contact').filtered('@links.@count == 0');
|
||||||
|
|
||||||
|
// Find contacts with no incoming friend links
|
||||||
|
let lonely = realm.objects('Contact').filtered('@links.Contact.friends.@count == 0');
|
||||||
|
```
|
||||||
|
|
|
@ -160,8 +160,7 @@ inline void alias_backlinks(parser::KeyPathMapping &mapping, const realm::Shared
|
||||||
if (property.type == realm::PropertyType::LinkingObjects) {
|
if (property.type == realm::PropertyType::LinkingObjects) {
|
||||||
auto target_object_schema = schema.find(property.object_type);
|
auto target_object_schema = schema.find(property.object_type);
|
||||||
const TableRef table = ObjectStore::table_for_object_type(realm->read_group(), it->name);
|
const TableRef table = ObjectStore::table_for_object_type(realm->read_group(), it->name);
|
||||||
const TableRef target_table = ObjectStore::table_for_object_type(realm->read_group(), target_object_schema->name);
|
std::string native_name = "@links." + target_object_schema->name + "." + property.link_origin_property_name;
|
||||||
std::string native_name = "@links." + std::string(target_table->get_name()) + "." + property.link_origin_property_name;
|
|
||||||
mapping.add_mapping(table, property.name, native_name);
|
mapping.add_mapping(table, property.name, native_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +180,7 @@ typename T::Object ResultsClass<T>::create_filtered(ContextType ctx, const U &co
|
||||||
auto const &object_schema = collection.get_object_schema();
|
auto const &object_schema = collection.get_object_schema();
|
||||||
DescriptorOrdering ordering;
|
DescriptorOrdering ordering;
|
||||||
parser::KeyPathMapping mapping;
|
parser::KeyPathMapping mapping;
|
||||||
|
mapping.set_backlink_class_prefix(ObjectStore::table_name_for_object_type(""));
|
||||||
alias_backlinks(mapping, realm);
|
alias_backlinks(mapping, realm);
|
||||||
|
|
||||||
parser::ParserResult result = parser::parse(query_string);
|
parser::ParserResult result = parser::parse(query_string);
|
||||||
|
|
|
@ -109,24 +109,49 @@ module.exports = {
|
||||||
let english = realm.create('Language', {name: 'English'});
|
let english = realm.create('Language', {name: 'English'});
|
||||||
let french = realm.create('Language', {name: 'French'});
|
let french = realm.create('Language', {name: 'French'});
|
||||||
let danish = realm.create('Language', {name: 'Danish'});
|
let danish = realm.create('Language', {name: 'Danish'});
|
||||||
|
let latin = realm.create('Language', {name: 'Latin'});
|
||||||
let canada = realm.create('Country', {name: 'Canada', languages: [english, french]});
|
let canada = realm.create('Country', {name: 'Canada', languages: [english, french]});
|
||||||
let denmark = realm.create('Country', {name: 'Denmark', languages: [danish, english]});
|
let denmark = realm.create('Country', {name: 'Denmark', languages: [danish, english]});
|
||||||
let france = realm.create('Country', {name: 'France', languages: [french, english]});
|
let france = realm.create('Country', {name: 'France', languages: [french, english]});
|
||||||
});
|
});
|
||||||
let languages = realm.objects('Language');
|
let languages = realm.objects('Language');
|
||||||
let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3');
|
{
|
||||||
TestCase.assertEqual(spokenInThreeCountries.length, 1);
|
let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3');
|
||||||
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
|
TestCase.assertEqual(spokenInThreeCountries.length, 1);
|
||||||
let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2');
|
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
|
||||||
TestCase.assertEqual(spokenInTwoCountries.length, 1);
|
let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2');
|
||||||
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
|
TestCase.assertEqual(spokenInTwoCountries.length, 1);
|
||||||
let spokenInOneCountry = languages.filtered('spokenIn.@count == 1');
|
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
|
||||||
TestCase.assertEqual(spokenInOneCountry.length, 1);
|
let spokenInOneCountry = languages.filtered('spokenIn.@count == 1');
|
||||||
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
|
TestCase.assertEqual(spokenInOneCountry.length, 1);
|
||||||
let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"');
|
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
|
||||||
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
|
let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"');
|
||||||
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
|
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
|
||||||
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
|
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
|
||||||
|
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
|
||||||
|
}
|
||||||
|
// check the same but using the unnamed relationship which is available to users
|
||||||
|
{
|
||||||
|
let spokenInThreeCountries = languages.filtered('@links.Country.languages.@count == 3');
|
||||||
|
TestCase.assertEqual(spokenInThreeCountries.length, 1);
|
||||||
|
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
|
||||||
|
let spokenInTwoCountries = languages.filtered('@links.Country.languages.@count == 2');
|
||||||
|
TestCase.assertEqual(spokenInTwoCountries.length, 1);
|
||||||
|
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
|
||||||
|
let spokenInOneCountry = languages.filtered('@links.Country.languages.@count == 1');
|
||||||
|
TestCase.assertEqual(spokenInOneCountry.length, 1);
|
||||||
|
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
|
||||||
|
let languagesSpokenInCanada = languages.filtered('@links.Country.languages.name ==[c] "canada"');
|
||||||
|
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
|
||||||
|
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
|
||||||
|
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
|
||||||
|
}
|
||||||
|
let notSpokenInAnyCountry = languages.filtered('@links.@count == 0'); // no incoming links over any relationships to the object
|
||||||
|
TestCase.assertEqual(notSpokenInAnyCountry.length, 1);
|
||||||
|
TestCase.assertEqual(notSpokenInAnyCountry[0].name, 'Latin');
|
||||||
|
let notSpokenMethod2 = languages.filtered('@links.Country.languages.@count == 0'); // links of a specific relationship are 0
|
||||||
|
TestCase.assertEqual(notSpokenMethod2.length, 1);
|
||||||
|
TestCase.assertEqual(notSpokenMethod2[0].name, 'Latin');
|
||||||
},
|
},
|
||||||
|
|
||||||
testMethod: function() {
|
testMethod: function() {
|
||||||
|
|
Loading…
Reference in New Issue