【问题标题】:MongoDb Java filter for value in listMongoDb Java过滤器列表中的值
【发布时间】:2026-01-15 17:50:02
【问题描述】:

我有一个数据库对象,其中包含一个也是对象的字段,如下所示:

public class PrdVersionOverviewDbData {

    public static final String FIELD_SPECIFICATION_ENTRY_POINTER = "specificiationEntryPointer";
    
    @BsonProperty(FIELD_SPECIFICATION_ENTRY_POINTER)
    private MongodbSpecificationEntryPointer specificiationEntryPointer;

    [...]
}

现在,我有一个List<MongodbSpecificationEntryPointer>,我想查找所有PrdVersionOverviewDbData,其中specificiationEntryPointer 是列表中的任何一个。自发地,我尝试使用这样的in 过滤器来解决这个问题:

Bson filter = Filters.in(PrdVersionOverviewDbData.FIELD_SPECIFICATION_ENTRY_POINTER, specificiationEntryPointerList);

但是,出于某种奇怪的原因,运行该过滤器总是只返回一个空列表。

相比之下,下面的逻辑给了我想要的结果:

    public List<PrdVersionOverviewDbData> readPrdVersionsContainingAnyOfSpecificationPointers(
        List<MongodbSpecificationEntryPointer> specificationPointerList
    ) {
        List<PrdVersionOverviewDbData> allPrdVersionOverviews = readObjectList();
        List<PrdVersionOverviewDbData> prdVersionOverviewsContainingSpecificationPointer = new ArrayList<>();
        for (PrdVersionOverviewDbData prdVersionOverviewDbData : allPrdVersionOverviews) {
            if(prdVersionOverviewDbData.containsAny(specificationPointerList)) {
                prdVersionOverviewsContainingSpecificationPointer.add(prdVersionOverviewDbData);
            }
        }
        return prdVersionOverviewsContainingSpecificationPointer;
    }
public class PrdVersionOverviewDbData{

    public static final String FIELD_SPECIFICATION_ENTRY_POINTER = "specificiationEntryPointer";
    
    @BsonProperty(FIELD_SPECIFICATION_ENTRY_POINTER)
    private MongodbSpecificationEntryPointer specificiationEntryPointer;

    [...]

    public boolean containsAny(
        List<MongodbSpecificationEntryPointer> specificationPointerList
    ) {
        return specificationPointerList.contains(specificiationEntryPointer);
    }
}

当然,这是非常低效的,因为它首先需要从 MongoDB 读取所有数据,然后对其进行迭代。所以我的问题是:我在过滤器上做错了什么?这样做的正确方法是什么?

【问题讨论】:

    标签: java mongodb filter


    【解决方案1】:

    我现在已经弄清楚是什么原因造成的,以及如何解决它。

    本质上,Filters.in 是用于这种情况的正确过滤器。问题是对于某些对象,MongoDB 无法比较它们。这可能与所述对象是抽象类的子对象有关,但我对此不是 100% 确定。

    无论如何,我设法解决这个问题的方法是,我没有通过 MongodbSpecificationEntryPointer(本质上只是一个 ObjectId 的包装器)进行比较,而是直接通过 ObjectId 进行比较,所以现在我的逻辑看起来有点像这样:

        private static final String FIELD_PATH_SPECIFICATION_POINTER_OBJECT_ID
            = PrdVersionOverviewDbData.FIELD_SPECIFICATION_ENTRY_POINTER
                + "."
                + MongodbEntryPointer.MONGO_DB_ID_FIELD;
        
        public List<PrdVersionOverviewDbData> getPrdVersionOverviewsInSpecifications(
            List<Specification> specificationsInFolder
        ) {
            List<ObjectId> specificationObjectIdList
                = toSpecificationObjectIdList(specificationsInFolder);
            
            return readObjectListWithFieldContainingAny(
                FIELD_PATH_SPECIFICATION_POINTER_OBJECT_ID,
                specificationObjectIdList
            );
        }
    
        public List<T> readObjectListWithFieldContainingAny(
            String fieldName,
            Iterable<?> fieldValue
        ) {
            Bson filter = Filters.in(fieldName, fieldValue);
            return readObjectList(filter);
        }
        
        private List<ObjectId> toSpecificationObjectIdList(
            List<Specification> specificationsInFolder
        ) {
            return specificationsInFolder.stream()
                .map(Specification::getObjectId)
                .collect(Collectors.toList());
        }
    

    【讨论】: