Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions templates/android/library/src/main/java/io/package/Query.kt.twig
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,15 @@ class Query(
*/
fun elemMatch(attribute: String, queries: List<String>) = Query("elemMatch", attribute, queries.map { it.fromJson<Map<String, Any>>() }).toJson()

/**
* Constrain populated related documents on a relationship attribute.
*
* @param attribute The relationship attribute to query.
* @param queries Filter, order, select, and pagination queries applied to related documents.
* @returns The query string.
*/
fun relationship(attribute: String, queries: List<String>) = Query("relationship", attribute, queries.map { it.fromJson<Map<String, Any>>() }).toJson()

/**
* Filter resources where attribute is at a specific distance from the given coordinates.
*
Expand Down Expand Up @@ -990,6 +999,8 @@ class Query(

fun elemMatch(attribute: String, queries: List<String>) = push(Query.elemMatch(attribute, queries))

fun relationship(attribute: String, queries: List<String>) = push(Query.relationship(attribute, queries))

fun distanceEqual(attribute: String, values: List<Any>, distance: Number, meters: Boolean = true) = push(Query.distanceEqual(attribute, values, distance, meters))

fun distanceNotEqual(attribute: String, values: List<Any>, distance: Number, meters: Boolean = true) = push(Query.distanceNotEqual(attribute, values, distance, meters))
Expand Down
10 changes: 10 additions & 0 deletions templates/dart/lib/query.dart.twig
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,16 @@ class Query {
).toString();
}

/// Constrain populated related documents on a relationship attribute.
///
/// [attribute] The relationship attribute to query.
/// [queries] Filter, order, select, and pagination queries applied to related documents.
static String relationship(String attribute, List<String> queries) => Query._(
'relationship',
attribute,
queries.map((query) => jsonDecode(query)).toList(),
).toString();

/// Specify which attributes should be returned by the API call.
static String select(List<String> attributes) =>
Query._('select', null, attributes).toString();
Expand Down
3 changes: 3 additions & 0 deletions templates/dart/lib/query/builder.dart.twig
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ class QueryBuilder {
QueryBuilder elemMatch(String attribute, List<String> queries) =>
_push(Query.elemMatch(attribute, queries));

QueryBuilder relationship(String attribute, List<String> queries) =>
_push(Query.relationship(attribute, queries));

QueryBuilder distanceEqual(
String attribute,
List<dynamic> values,
Expand Down
18 changes: 18 additions & 0 deletions templates/dart/test/query_test.dart.twig
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,24 @@ void main() {
expect(query['values'][1]['values'], [18]);
});

test('returns relationship', () {
final inner1 = Query.equal('approved', true);
final inner2 = Query.limit(2);

final query = jsonDecode(Query.relationship('comments', [inner1, inner2]));

expect(query['attribute'], 'comments');
expect(query['method'], 'relationship');
expect(query['values'].length, 2);

expect(query['values'][0]['method'], 'equal');
expect(query['values'][0]['attribute'], 'approved');
expect(query['values'][0]['values'], [true]);

expect(query['values'][1]['method'], 'limit');
expect(query['values'][1]['values'], [2]);
});

test('returns createdBefore', () {
final query = jsonDecode(Query.createdBefore('2023-01-01'));
expect(query['attribute'], '\$createdAt');
Expand Down
18 changes: 18 additions & 0 deletions templates/deno/src/query.ts.twig
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,20 @@ export class Query {
queries.map((query) => JSON.parse(query))
).toString();

/**
* Constrain populated related documents on a relationship attribute.
*
* @param {string} attribute The relationship attribute to query.
* @param {string[]} queries Filter, order, select, and pagination queries applied to related documents.
* @returns {string}
*/
static relationship = (attribute: string, queries: string[]): string =>
new Query(
"relationship",
attribute,
queries.map((query) => JSON.parse(query))
).toString();

/**
* Filter resources where attribute is at a specific distance from the given coordinates.
*
Expand Down Expand Up @@ -813,6 +827,10 @@ export namespace Query {
return this.push(Query.elemMatch(attribute, queries));
}

relationship(attribute: string, queries: string[]): this {
return this.push(Query.relationship(attribute, queries));
}

distanceEqual(attribute: string, values: any[], distance: number, meters: boolean = true): this {
return this.push(Query.distanceEqual(attribute, values, distance, meters));
}
Expand Down
16 changes: 16 additions & 0 deletions templates/deno/test/query.test.ts.twig
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,22 @@ describe('Query', () => {
assertEquals(parsed.values[1].values, [18]);
});

test('relationship', () => {
const inner1 = Query.equal('approved', true);
const inner2 = Query.limit(2);
const result = Query.relationship('comments', [inner1, inner2]);
const parsed = JSON.parse(result);

assertEquals(parsed.method, 'relationship');
assertEquals(parsed.attribute, 'comments');
assertEquals(parsed.values.length, 2);
assertEquals(parsed.values[0].method, 'equal');
assertEquals(parsed.values[0].attribute, 'approved');
assertEquals(parsed.values[0].values, [true]);
assertEquals(parsed.values[1].method, 'limit');
assertEquals(parsed.values[1].values, [2]);
});

test('createdBefore', () => assertEquals(
parsed(Query.createdBefore('2023-01-01').toString()),
{
Expand Down
14 changes: 14 additions & 0 deletions templates/dotnet/Package/Query.cs.twig
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,20 @@ namespace {{ spec.info.title | caseUcfirst }}
return new Query("elemMatch", attribute, parsed).ToString();
}

/// <summary>
/// Constrain populated related documents on a relationship attribute.
/// </summary>
/// <param name="attribute">The relationship attribute to query.</param>
/// <param name="queries">Filter, order, select, and pagination queries applied to related documents.</param>
/// <returns>The query string.</returns>
public static string Relationship(string attribute, List<string> queries)
{
var parsed = queries
.Select(q => JsonSerializer.Deserialize<Query>(q, Client.DeserializerOptions) as object)
.ToList();
return new Query("relationship", attribute, parsed).ToString();
}

public static string DistanceEqual(string attribute, object values, double distance, bool meters = true)
{
return new Query("distanceEqual", attribute, new List<object> { new List<object> { values, distance, meters } }).ToString();
Expand Down
5 changes: 5 additions & 0 deletions templates/dotnet/Package/Query/Builder.cs.twig
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ namespace {{ spec.info.title | caseUcfirst }}
return Push(Query.ElemMatch(attribute, queries));
}

public Builder Relationship(string attribute, List<string> queries)
{
return Push(Query.Relationship(attribute, queries));
}

public Builder DistanceEqual(string attribute, object values, double distance, bool meters = true)
{
return Push(Query.DistanceEqual(attribute, values, distance, meters));
Expand Down
21 changes: 21 additions & 0 deletions templates/go/query.go.twig
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,27 @@ func ElemMatch(attribute string, queries []string) string {
})
}

// Relationship constrains populated related documents on a relationship attribute.
//
// attribute: The relationship attribute to query.
// queries: Filter, order, select, and pagination queries applied to related documents.
// Returns the query string.
func Relationship(attribute string, queries []string) string {
var parsedQueries []interface{}
for _, query := range queries {
var q interface{}
if err := json.Unmarshal([]byte(query), &q); err != nil {
continue
}
parsedQueries = append(parsedQueries, q)
}
return parseQuery(queryOptions{
Method: "relationship",
Attribute: &attribute,
Values: &parsedQueries,
})
}

func aliasedQuery(method, attribute, alias string) string {
options := queryOptions{
Method: method,
Expand Down
4 changes: 4 additions & 0 deletions templates/go/query/builder.go.twig
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ func (b *Builder) ElemMatch(attribute string, queries []string) *Builder {
return b.push(ElemMatch(attribute, queries))
}

func (b *Builder) Relationship(attribute string, queries []string) *Builder {
return b.push(Relationship(attribute, queries))
}

func (b *Builder) DistanceEqual(attribute string, values []interface{}, distance float64, meters bool) *Builder {
return b.push(DistanceEqual(attribute, values, distance, meters))
}
Expand Down
22 changes: 22 additions & 0 deletions templates/go/query_test.go.twig
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,28 @@ func TestOr(t *testing.T) {
}
}

func TestRelationship(t *testing.T) {
q1 := Equal("approved", true)
q2 := Limit(2)
q := Relationship("comments", []string{q1, q2})

var data map[string]interface{}
if err := json.Unmarshal([]byte(q), &data); err != nil {
t.Fatal(err)
}

if data["method"] != "relationship" {
t.Errorf("Expected relationship, got %v", data["method"])
}
if data["attribute"] != "comments" {
t.Errorf("Expected comments, got %v", data["attribute"])
}
values := data["values"].([]interface{})
if len(values) != 2 {
t.Errorf("Expected 2 subqueries, got %d", len(values))
}
}

func TestCountWithAlias(t *testing.T) {
q := Count("*", "total")
var data map[string]interface{}
Expand Down
11 changes: 11 additions & 0 deletions templates/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ class Query(
*/
fun elemMatch(attribute: String, queries: List<String>) = Query("elemMatch", attribute, queries.map { it.fromJson<Query>() }).toJson()

/**
* Constrain populated related documents on a relationship attribute.
*
* @param attribute The relationship attribute to query.
* @param queries Filter, order, select, and pagination queries applied to related documents.
* @returns The query string.
*/
fun relationship(attribute: String, queries: List<String>) = Query("relationship", attribute, queries.map { it.fromJson<Query>() }).toJson()

/**
* Filter resources where attribute is at a specific distance from the given coordinates.
*
Expand Down Expand Up @@ -684,6 +693,8 @@ class Query(

fun elemMatch(attribute: String, queries: List<String>) = push(Query.elemMatch(attribute, queries))

fun relationship(attribute: String, queries: List<String>) = push(Query.relationship(attribute, queries))

fun distanceEqual(attribute: String, values: List<Any>, distance: Number, meters: Boolean = true) = push(Query.distanceEqual(attribute, values, distance, meters))

fun distanceNotEqual(attribute: String, values: List<Any>, distance: Number, meters: Boolean = true) = push(Query.distanceNotEqual(attribute, values, distance, meters))
Expand Down
12 changes: 12 additions & 0 deletions templates/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ class QueryTest {
assertEquals("on", method(Query.on("\$id", "customerId")))
}

@Test
fun relationship() {
val query = Query.relationship("comments", listOf(Query.equal("approved", true), Query.limit(2)))
val json = JsonParser.parseString(query).asJsonObject
assertEquals("relationship", json.get("method").asString)
assertEquals("comments", json.get("attribute").asString)
val values = json.get("values").asJsonArray
assertEquals("equal", values[0].asJsonObject.get("method").asString)
assertEquals("limit", values[1].asJsonObject.get("method").asString)
assertEquals(listOf(query), Query.builder().relationship("comments", listOf(Query.equal("approved", true), Query.limit(2))).build())
}

@Test
fun nestedLeftJoin() {
val json = JsonParser.parseString(
Expand Down
13 changes: 13 additions & 0 deletions templates/php/src/Query.php.twig
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,19 @@ class Query implements \JsonSerializable, \Stringable
return new Query('elemMatch', $attribute, $queries)->__toString();
}

/**
* Constrain populated related documents on a relationship attribute.
*
*/
public static function relationship(string $attribute, array $queries): string
{
foreach ($queries as &$query) {
$query = \json_decode($query, true);
}

return new Query('relationship', $attribute, $queries)->__toString();
}

/**
* Distance Equal
*/
Expand Down
5 changes: 5 additions & 0 deletions templates/php/src/Query/Builder.php.twig
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ class Builder
return $this->push(Query::elemMatch($attribute, $queries));
}

public function relationship(string $attribute, array $queries): self
{
return $this->push(Query::relationship($attribute, $queries));
}

/**
* @param array<mixed> $values
*/
Expand Down
19 changes: 19 additions & 0 deletions templates/php/tests/QueryTest.php.twig
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,25 @@ final class QueryTest extends TestCase
$this->assertSame([18], $query['values'][1]['values']);
}

public function testRelationship(): void
{
$inner1 = Query::equal('approved', true);
$inner2 = Query::limit(2);

$query = json_decode(Query::relationship('comments', [$inner1, $inner2]), true);

$this->assertSame('comments', $query['attribute']);
$this->assertSame('relationship', $query['method']);
$this->assertCount(2, $query['values']);

$this->assertSame('equal', $query['values'][0]['method']);
$this->assertSame('approved', $query['values'][0]['attribute']);
$this->assertSame([true], $query['values'][0]['values']);

$this->assertSame('limit', $query['values'][1]['method']);
$this->assertSame([2], $query['values'][1]['values']);
}

public function testCreatedBefore(): void
{
$query = json_decode(Query::createdBefore('2023-01-01'), true);
Expand Down
17 changes: 17 additions & 0 deletions templates/python/package/query.py.twig
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,20 @@ class Query:
"""
return str(Query("elemMatch", attribute, [json.loads(query) for query in queries]))

@staticmethod
def relationship(attribute, queries):
"""
Constrain populated related documents on a relationship attribute.

Args:
attribute: The relationship attribute to query.
queries: Filter, order, select, and pagination queries applied to related documents.

Returns:
The query string.
"""
return str(Query("relationship", attribute, [json.loads(query) for query in queries]))

@staticmethod
def distance_equal(attribute, values, distance, meters=True):
return str(Query("distanceEqual", attribute, [[values, distance, meters]]))
Expand Down Expand Up @@ -594,6 +608,9 @@ class Query:
def elem_match(self, attribute, queries):
return self._push(Query.elem_match(attribute, queries))

def relationship(self, attribute, queries):
return self._push(Query.relationship(attribute, queries))

def distance_equal(self, attribute, values, distance, meters=True):
return self._push(Query.distance_equal(attribute, values, distance, meters))

Expand Down
18 changes: 18 additions & 0 deletions templates/react-native/src/query.ts.twig
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,20 @@ export class Query {
queries.map((query) => JSONbig.parse(query)),
).toString();

/**
* Constrain populated related documents on a relationship attribute.
*
* @param {string} attribute The relationship attribute to query.
* @param {string[]} queries Filter, order, select, and pagination queries applied to related documents.
* @returns {string}
*/
static relationship = (attribute: string, queries: string[]): string =>
new Query(
'relationship',
attribute,
queries.map((query) => JSONbig.parse(query)),
).toString();

/**
* Filter resources where attribute is at a specific distance from the given coordinates.
*
Expand Down Expand Up @@ -960,6 +974,10 @@ export namespace Query {
return this.push(Query.elemMatch(attribute, queries));
}

relationship(attribute: string, queries: string[]): this {
return this.push(Query.relationship(attribute, queries));
}

distanceEqual(
attribute: string,
values: any[],
Expand Down
Loading
Loading