Spring Data Mongo 属性表达式查询不返回任何结果

问题描述 投票:0回答:1

我最近开始从事 Spring Boot 项目并选择 MongoDB 作为我的数据库。我有以下文档结构。

以下是用户文档结构。

@Data
@Builder(setterPrefix = "with")
@Document(collection = "users")
@JsonIgnoreProperties(value = {"password", "createdAt", "updatedAt"}, allowSetters = true)
public class User {

    @Id
    @Indexed
    private String id;

    @Indexed(unique = true, direction = IndexDirection.DESCENDING)
    private String username;

    private String name;

    private String password;

    @CreatedDate
    private Date createdAt;

    @LastModifiedDate
    private Date updatedAt;
}

我的借用文档结构如下。

@Document(collection = "borrows")
@Data
@SuperBuilder(setterPrefix = "with")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@AllArgsConstructor
@NoArgsConstructor
public abstract class Borrow {

    @Id
    @EqualsAndHashCode.Include
    private String id;

    @DocumentReference
    private User borrower;

    @DocumentReference
    private User borowee;

    private Date expectedReturnDate;

    private Date actualReturnDate;

    private String place;

    private String occasion;

    private BorrowStatus status;

    public abstract String getType();
}

以及 Borrow 的两个子类如下。

借钱

@Document(collection = "borrows")
@Data
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
@SuperBuilder(setterPrefix = "with")
@BsonDiscriminator(key = "type", value = "Money")
public class BorrowMoney extends Borrow{

    private Double amount;

    @Override
    public String getType() {
        return "Money";
    }
}
@Document(collection = "borrows")
@Data
@SuperBuilder(setterPrefix = "with")
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
@BsonDiscriminator(key = "type", value = "Items")
@AllArgsConstructor
@NoArgsConstructor
public class BorrowItem extends Borrow{

    private String itemName;

    private String description;

    @Override
    public String getType() {
        return "Items";
    }
}

提醒文档结构

@Data
@Builder
@Document(collection = "reminders")
public class Reminder {
    @Id
    private String id;

    @DocumentReference
    private Borrow borrow;

    private String message;

    private String header;

    @Indexed
    private String borrower;

    @Indexed
    private String borowee;

    private boolean read;

    @CreatedDate
    private Date createdAt;

    @LastModifiedDate
    private Date updatedAt;
}

我正在尝试使用用户的 id 来获取当前登录用户的所有提醒。 我按照官方

spring-data-mongo
文档来理解属性表达式查询。

我在ReminderRepository中编写了以下方法。

@Repository
public interface ReminderRepository extends MongoRepository<Reminder, String> {

    List<Reminder> findByBorrowBorrowerId(String id);
}

但是,尽管记录已经存在,但执行此操作始终返回 0 结果。

2024-03-30 17:05:26.998 DEBUG 27280 [nio-3080-exec-4,6607f8fe755cc27c4afe5cfe81fb8f8b,75158ed32fd3ebcc] o.s.d.m.c.MongoTemplate        : find using query: { "borrow" : { "$oid" : "6605a6ea9796e7405763c9ac"}} fields: Document{{}} for class: class com.kitaab.hisaab.ledger.entity.Reminder in collection: reminders

我看到上面的查询是由

spring-data-mongo
生成的,这里的 id
6605a6ea9796e7405763c9ac
实际上是用户的而不是借用的。

根据文档,它应该采用属性路径borrow.borrower.id。

还尝试使用

@Query("{ 'borrow.borrower.id' : ?0 }}")
注释。然而,没有突破。

帮我解决这个问题。

存储库链接

编辑1:

只是重现器代码

mongodb spring-boot spring-data-jpa mongodb-query spring-data-mongodb
1个回答
0
投票

我不是 mongoDB 专家,但据我了解,Spring Data MongoDB 不支持直接使用 MongoRepository 接口查询嵌套字段(超过 2 个)。这是由于 MongoDB 处理文档之间引用的方式所致。

下面的代码返回结果

@Service
public class ReminderService {

    @Autowired
    private MongoTemplate mongoTemplate;

    public List<Reminder> getRemindersByUserId(String userId) {
        Query borrowQuery = new Query();
        borrowQuery.addCriteria(Criteria.where("borrower.id").is(userId));
        List<Borrow> borrows = mongoTemplate.find(borrowQuery, Borrow.class);

        List<ObjectId> borrowIds = borrows.stream()
                .map(Borrow::getId)
                .collect(Collectors.toList());

        Query reminderQuery = new Query();
        reminderQuery.addCriteria(Criteria.where("borrow.id").in(borrowIds));
        return mongoTemplate.find(reminderQuery, Reminder.class);
    }
}

但是您可以更改现有的数据结构,不要深入采用继承方法,而使用

@DocumentReference
只需将所有内容分开并保留 id。例子

public class Reminder {
    @Id
    private ObjectId id;
    private String borrowId;
    private String borrowerId;
    private String borroweeId;
    private String message;
}

这样 mongoDB 将运行得更快,并且

MongoRepository
将按照您的预期进行响应。毕竟 mongodb 是一个文档数据库而不是 RDBMS。

© www.soinside.com 2019 - 2024. All rights reserved.