Initial work for unnamed backlink queries and @links.@count tests
This commit is contained in:
parent
c3a83f1866
commit
591aa9fee7
|
@ -95,3 +95,21 @@ Example:
|
|||
// 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');
|
||||
```
|
||||
|
||||
### 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) {
|
||||
auto target_object_schema = schema.find(property.object_type);
|
||||
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." + std::string(target_table->get_name()) + "." + property.link_origin_property_name;
|
||||
std::string native_name = "@links." + target_object_schema->name + "." + property.link_origin_property_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();
|
||||
DescriptorOrdering ordering;
|
||||
parser::KeyPathMapping mapping;
|
||||
mapping.set_backlink_class_prefix(ObjectStore::table_name_for_object_type(""));
|
||||
alias_backlinks(mapping, realm);
|
||||
|
||||
parser::ParserResult result = parser::parse(query_string);
|
||||
|
|
|
@ -109,24 +109,49 @@ module.exports = {
|
|||
let english = realm.create('Language', {name: 'English'});
|
||||
let french = realm.create('Language', {name: 'French'});
|
||||
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 denmark = realm.create('Country', {name: 'Denmark', languages: [danish, english]});
|
||||
let france = realm.create('Country', {name: 'France', languages: [french, english]});
|
||||
});
|
||||
let languages = realm.objects('Language');
|
||||
let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3');
|
||||
TestCase.assertEqual(spokenInThreeCountries.length, 1);
|
||||
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
|
||||
let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2');
|
||||
TestCase.assertEqual(spokenInTwoCountries.length, 1);
|
||||
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
|
||||
let spokenInOneCountry = languages.filtered('spokenIn.@count == 1');
|
||||
TestCase.assertEqual(spokenInOneCountry.length, 1);
|
||||
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
|
||||
let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"');
|
||||
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
|
||||
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
|
||||
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
|
||||
{
|
||||
let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3');
|
||||
TestCase.assertEqual(spokenInThreeCountries.length, 1);
|
||||
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
|
||||
let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2');
|
||||
TestCase.assertEqual(spokenInTwoCountries.length, 1);
|
||||
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
|
||||
let spokenInOneCountry = languages.filtered('spokenIn.@count == 1');
|
||||
TestCase.assertEqual(spokenInOneCountry.length, 1);
|
||||
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
|
||||
let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"');
|
||||
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue