Spring 数据 Mongo 使用 ObjectID 的自定义存储库查询

Spring Data Mongo Custom Repository Query with ObjectID

我有一个 mongo 查询,我想将其实现为 Spring Mongo 存储库

db.collection.find({ 'items': 
    { $elemMatch: { 
        'refund.$id' :  ObjectId('5638cab2e4b07ff212618d7e') 
        } 
    }
}) 

我的存储库界面是

@Query("{ 'items': { $elemMatch: { 'refund.$id' :  ObjectId(?0) } } }")
RMA findRMAByItemRefund(String refundId);

它抛出 JSONParseException

Caused by: com.mongodb.util.JSONParseException: 
{ 'items': { $elemMatch: { 'refund.$id' :  ObjectId("_param_0") } } }
                                       ^
    at com.mongodb.util.JSONParser.parse(JSON.java:216)

试试这个

@Query("{ 'items': { $elemMatch: { 'refund.id' :  ?0 } } }")
RMA findRMAByItemRefund(String refundId);

根据我的经验,?0 应该独立使用,而不是用作 mongo 函数参数。

另外,是$id你自己的假设还是字段实际存储为$id。如果没有,我会选择 refund.id

由于接受的解决方案在我的案例中没有产生任何结果,我不得不找到另一个解决方案,即:

我没有使用通过 @Query(...) 定义的自动生成的查询功能,而是选择手动构建用于查询 mongo 的 DBObject,并将该功能定义为 default在接口中实现,从而保持它 "clean" (" - 因为不得不引入一个 _query 方法)

注意:此解决方案仅适用于Java 1.8+

public interface SomeRepository extends MongoRepository<SomeEntity, String> {

    @Query("{'nestedEntity._id': ?0}")
    SomeEntity findByNestedEntityId_DoesntWork(String nestedEntityId);

    @Query("?0")
    SomeEntity _query(DBObject query);

    default SomeEntity findByNestedEntityId(String nestedEntityId) {
        DBObject queryObject = BasicDBObjectBuilder
            .start("nestedEntity._id", new ObjectId(nestedEntityId))
            .get();

        return this._query(queryObject);
    }
}

我想我的问题有点不同,但由于我无法在任何地方找到答案,所以我认为值得一提。 基本上我想通过 ObjectId 和 userId 进行搜索,所以这是我所做的:

@Query("{ '_id': ?0, 'userId': ?1 }")
T findByObjectIdAndUserId(final ObjectId objectId, final Long userId);

这是 mongo 文档中的示例对象:

{ 
    "_id" : ObjectId("5c052a43f14008522c1c90c8"), 
    "_class" : "com.gdn.payment.report.entity.ReportDocument", 
    "status" : "DONE", 
    "report" : {
        "id" : ObjectId("5c0508bcf14008460015eb07"), 
        "startDate" : NumberLong(1542795843188), 
        "endDate" : NumberLong(1543568857157), 
        "fields" : [
            "customerInfo.billingAddress.streetAddress", 
            "customerInfo.name", 
            "items[*].name", 
            "orderId", 
            "type"
        ]
    }
}

您只能通过使用 ObjectId 数据类型来创建用于搜索 report.id 的存储库方法,我试过仅使用字符串但它不起作用,这是我的存储库方法:

Page<ReportDocument> findByReport_id(ObjectId reportId, Pageable pageable)

要创建 ObjectId,您可以使用:

new ObjectId({input-reportId-string})

我建议在顶部使用 Spring 数据 Derived Queries. You can also use QueryDsl

然后您就可以编写更复杂的查询,而不必处理查询语法和解析等次要问题。