Skip to content

Scanning by nested properties seems to not work #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sasagonz opened this issue Jan 11, 2018 · 13 comments
Open

Scanning by nested properties seems to not work #114

sasagonz opened this issue Jan 11, 2018 · 13 comments

Comments

@sasagonz
Copy link

sasagonz commented Jan 11, 2018

Hi.

If I run this by command line I get results:

aws dynamodb scan --table-name Person --filter-expression "address.countryCode = :value" --expression-attribute-values '{":value":{"S":"ES"}}' --endpoint-url http://localhost:8000

See that I'm searching by person.address.countryCode.

Ok, I have Person configured with @DynamoDBTable and the address attribute with @DynamoDBDocument. Then, in PersonRepository, I have:

@EnableScan List<Person> findByAddressCountryCode( @Param("addressCountryCode") String addressCountryCode);

But when I execute the method in JUnit, it doesn't return anything. Debugging, I see that in DynamoDBScanExpression, only scanFilter attribute is used, and not expressionAttributeNames and expressionAttributeValues, like by command line. The thing is that I cannot see which request is sent to my local dynamodb server. Maybe it is sending the key/value [countryCode / ES] instead of [address.countryCode / ES]. I'm suspecting that because I see (debugging) that in ScanRequestMarshaller, tableName is set to Person and scanFilterMap contains the field countryCode, which doesn't correspond to Person but to Person.Address

Could anyone tell me if it is an already known problem or what I'm doing wrong?

NOTE: other JUnit methods that test other repository methods over Person works without problem. But always over basic attributes like Number or String.

Regards.

@derjust
Copy link
Owner

derjust commented Jan 11, 2018

Thanks for the detailed report.

I’m quite sure it’s not implemented at all. But for sure worth to add it.
Would you mind putting your Person/Address entities here?

@sasagonz
Copy link
Author

sasagonz commented Jan 12, 2018

Thanks for your quick response. Please see below the code:

public class PersonId implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;
    private String area;

    @DynamoDBRangeKey
    public String getArea() {
      return area;
    }

    @DynamoDBHashKey
    public String getName() {
      return name;
    }

    public PersonId() {}

    public PersonId(String name, String area) {
      this.name = name;
      this.area = area;
    }
    public void setName(String name) {
      this.name = name;
    }
    public void setArea(String area) {
      this.area = area;
    }
}
@DynamoDBTable(tableName = "Person")
public class Person {

    @Id
    private PersonId personId;

    private String phone;
    private Address address;

    @DynamoDBHashKey
    public String getName() {
        return personId != null ? personId.getName() : null;
    }

    @DynamoDBRangeKey
    public String getArea() {
        return personId != null ? personId.getArea() : null;
    }
    public Address getAddress() {
        return address;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public void setName(String name) {
        if (personId == null) {
            personId = new PersonId();
        }
        this.personId.setName(name);
    }
    public void setArea(String area) {
        if (personId == null) {
            personId = new PersonId();
        }
        this.personId.setArea(area);
    }
    public void setAddress(Address address) {
        this.address = address;
    }
}
@DynamoDBDocument
public class Address {
    private String city;
    private String country;

    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
}
public interface PersonRepository extends PagingAndSortingRepository<Person, PersonId> {

    Person findByNameAndArea(@Param("name") String name, @Param("name") String area);
    
    @EnableScan
    List<Person> findByArea(@Param("name") String area);
    
    @EnableScan
    List<Person> findByPhone(@Param("phone") String phone);
    
    @EnableScan
    List<Person> findByAddressCountry(@Param("country") String country);
}

@derjust derjust added this to the v5.0.2 milestone Jan 14, 2018
@derjust derjust modified the milestones: v5.0.2, v5.0.3 Mar 22, 2018
@parxier
Copy link

parxier commented Apr 21, 2018

Would love to use this feature. When is 5.0.3 planned to release? Also is there any workaround apart from writing completely custom repository method implementation? https://github.com/derjust/spring-data-dynamodb/wiki/Custom-repository-implementations
Thank you!

@derjust
Copy link
Owner

derjust commented Apr 23, 2018

@parxier There is no fixed time frame for 5.0.3.
Custom repositories are your only way for the time being.

@parxier
Copy link

parxier commented May 5, 2018

@derjust Thank you. Is 5.0.3-SNAPSHOT available somewhere centrally to try?

@derjust
Copy link
Owner

derjust commented May 13, 2018

SNAPSHOT builds are available via the OSSRH snapshot repository

@derjust derjust removed this from the v5.0.3 milestone Aug 11, 2018
@ghost
Copy link

ghost commented Aug 25, 2018

Hi derjust,

I understand the nested property search feature is not yet implemented and there is no timeframe. I just wanted a clarification related to this. In sasagonz's example, the address object is a simple nested reference. What if it was in a list? For example:

@DynamoDBTable(tableName = "Person")
public class Person {

    @Id
    private PersonId personId;

    private String phone;
    private List<Address> addressList;

In this case, is there any syntax that would enable me to search for Person instances that have ANY address with country code equal to 'XX'? I'm prepared to implement a custom repository, but just wanted to understand what the method name ought to be.

// Simple address reference
@EnableScan List<Person> findByAddressCountryCode( @Param("addressCountryCode") String addressCountryCode);

// Nested address list?
@EnableScan List<Person> findByAddressListCountryCode( @Param("addressCountryCode") String addressCountryCode);

Is it that the method name syntax is the same whether the nested reference is a simple object or array? Or is there supposed to be some different syntax for nested list traversal? Is there any syntax for giving quantifications such as For All / There Exists etc?

@VelDeveloper
Copy link

@derjust Do we have any update for this issue? I mean I am also facing the similar issue...I would like to query based on nested DynamoDB document and List of nested DynamoDB document. Any help would be really appreciated.

@varshavenkat93
Copy link

I would like to query using filter expressions too. Is there any update on this issue?

@remibantos
Copy link

@derjust,
I am very interested by this feature too. Any update on this?

@ghsatpute
Copy link

@derjust
I was also looking for this feature. It would be surely a great addition to the project.

This was added to 5.0.3 but later removed. Any particular reason? Any help that we can do to make this available in next release?

@valoricDe
Copy link

valoricDe commented Jul 9, 2020

How would a custom repository method look like?
Something like:

@Repository
interface PeopleRepository : CrudRepository<People, String>, CustomizedPeopleRepository {
  @EnableScan
  fun findBySsoID(ssoId: SsoId): Set<People>
}

interface CustomizedPeopleRepository {
  @EnableScan
  fun findByTenantsSsoID(ssoId: SsoId): Set<People>
}

@Repository
class PeopleRepositoryImpl(var dynamoDBOperations: DynamoDBOperations) : CustomizedPeopleRepository {
  override fun findByTenantSsoID(ssoId: SsoId): PaginatedScanList<People> {
    val scanExpr = DynamoDBScanExpression()
      .withFilterExpression("tenants[0].ssoId = :ssoId")
      .withExpressionAttributeValues(mapOf("ssoId" to AttributeValue(ssoId.toString())))
    return dynamoDBOperations.scan(People::class.java, scanExpr)
  }
}

? Do you have an idea how I can scan for all tenants[x].ssoId?

@ghost
Copy link

ghost commented Feb 21, 2022

is there any update on this issue. Is the fix available in latest release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants