Spring框架mongodb找到最相关的子文档

时间:2019-06-19 15:17:02

标签: java mongodb spring-data document

我有一段代码可以使用条件从mongodb中找到相关文档和子文档,我的代码可以正常工作,但是现在我希望将结果从顶部匹配到最小匹配,例如,我有以下文档:< / p>

{"_id":{"_id":"48999"},"availableOnTV":true,"subType":"SHOW","type":"PROGRAM","titles":[{"language":"AR","title":"test"}],"descriptions":[{"language":"AR","shortDescription":"..."}],"url":{},"image":{"thumbnailImage":"....jpg"},"categoryIds":[{"_id":"7908"},{"_id":"7892"},{"_id":"7883"},{"_id":"7860"}],"personIds":[{"_id":"2411"}],"date":{"productionDate":"2001-01-01T00:00:00.000Z","sortDate":"2019-01-01T00:00:00.000Z","creationDate":"2013-11-03T05:30:00.000Z","modificationDate":"2018-02-14T16:56:38.000Z"},"pricingPlans":[{"_id":{"_id":"8881"},"date":{"startDate":"2013-11-02T05:30:00.000Z","endDate":"2067-01-01T00:00:00.000Z"},"type":"BROWSE_ONLY"}],"advertisementZone":{"advertisementZone":""},"_class":"Program"}

以及可能共享相同类别ID,人员ID和类型的其他文档,因此我设法获得了包含任何匹配项的所有文档,但是我想要返回的是在类别和人员中匹配度最高的结果在我的结果顶部,而在结果的最后只有一个匹配项。

这是我的代码正在执行此操作:

public Optional<ProductList> getRelated(String id, Set<String> pricingPlanIds, Pageable pageable)
        throws GenericException {
    Optional<ProductList> productList = this.getById(id, pricingPlanIds);
    if (!productList.isPresent()) {
        return Optional.empty();
    }

    Optional<ProductList> products = Optional.empty();

    for (Product product : productList.get().getProducts()) {
        Criteria buildExact = buildExact(product);
        Criteria buildSimilar = buildSimilar(product);
        Criteria buildLessSimilar = buildLessSimilar(product);

        Criteria productTypeCriteria = Criteria.where(RelatedParam.PRODUCT_TYPE.getParam())
                .is(product.getType().name());

        Criteria identicalProductCriteria = Criteria.where(RelatedParam.PRODUCT_ID.getParam())
                .ne(product.getId().getId());

        Criteria pricingPlanCriteria = new Criteria();
        pricingPlanCriteria = Criteria.where(RelatedParam.PRICING_PLAN_IDS.getParam()).in(pricingPlanIds);

        Criteria query = new Criteria();
        query.andOperator(productTypeCriteria, identicalProductCriteria, pricingPlanCriteria);
        query.orOperator(buildExact, buildSimilar, buildLessSimilar);



        products = aggregator.getRelated(pageable, query.getCriteriaObject());

        products.get().getProducts().stream().forEach(p -> System.out.println(p.getId().getId() + " " + p.getTitles()));
    }

    return products;
}

private Criteria buildLessSimilar(Product product) {
    Criteria criteria = new Criteria();
    if (product.getPersonIds() != null && !product.getPersonIds().isEmpty()) {
        criteria = Criteria.where(RelatedParam.PERSON.getParam())
                .in(product.getPersonIds().stream().map(p -> p.getId()).collect(Collectors.toList()));
    }

    return criteria;
}

private Criteria buildExact(Product product) {
    Criteria criteria = new Criteria();
    List<Criteria> criterias = new ArrayList<>();

    if (product.getPersonIds() != null && !product.getPersonIds().isEmpty()) {
        Criteria personsIdsCategories = Criteria.where(RelatedParam.PERSON.getParam())
                .in(product.getPersonIds().stream().map(p -> p.getId()).collect(Collectors.toList()));

        System.out.println(personsIdsCategories.getCriteriaObject());
        criterias.add(personsIdsCategories);
    }

    if (product.getCategoryIds() != null && !product.getCategoryIds().isEmpty()) {
        Criteria categoriesIdsCriteria = Criteria.where(RelatedParam.CATEGORY.getParam())
                .in(product.getCategoryIds().stream().map(c -> c.getId()).collect(Collectors.toList()));
        criterias.add(categoriesIdsCriteria);
    }

    if (product.getDate().getProductionDate() != null) { 
        LocalDate fromProductionDate = getProductionDate(product.getDate().getProductionDate());
        LocalDate toProductionDate = fromProductionDate.plusYears(1);
        Criteria productionDateCriteria = Criteria.where(RelatedParam.PRODUCTION_DATE.getParam()).gte(fromProductionDate).lt(toProductionDate);
        criterias.add(productionDateCriteria);
    }


    criteria.andOperator(criterias.toArray(new Criteria[criterias.size()]));



    return criteria;
}

private LocalDate getProductionDate(Date productionDate) {
    int year = productionDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().getYear();
    return LocalDate.of(year, 01, 01);
}

private Criteria buildSimilar(Product product) {
    Criteria criteria = new Criteria();
    List<Criteria> criterias = new ArrayList<>();

    if (product.getPersonIds() != null && !product.getPersonIds().isEmpty()) {
        Criteria personsIdsCategories = Criteria.where(RelatedParam.PERSON.getParam())
                .in(product.getPersonIds().stream().map(p -> p.getId()).collect(Collectors.toList()));
        criterias.add(personsIdsCategories);
    }

    if (product.getCategoryIds() != null && !product.getCategoryIds().isEmpty()) {
        Criteria categoriesIdsCriteria = Criteria.where(RelatedParam.CATEGORY.getParam())
                .in(product.getCategoryIds().stream().map(c -> c.getId()).collect(Collectors.toList()));
        criterias.add(categoriesIdsCriteria);
    }

    if (product.getDate().getProductionDate() != null) {
        LocalDate fromProductionDate = getProductionDate(product.getDate().getProductionDate());
        LocalDate toProductionDate = fromProductionDate.plusYears(1);
        Criteria productionDateCriteria = Criteria.where(RelatedParam.PRODUCTION_DATE.getParam()).gte(fromProductionDate).lt(toProductionDate);
        criterias.add(productionDateCriteria);
    }

    criteria.orOperator(criterias.toArray(new Criteria[criterias.size()]));
    return criteria;
}

这是我一直在尝试达到期望结果的方法,但仅根据以下搜索结果使用硬编码值:Sorting by relevance with MongoDB

    AggregateIterable<Document> output = collection.aggregate(Arrays.asList(
            new Document("$match", cat),
            new Document("$match", per),
            new Document("$match", type),
            new Document("$unwind", "$categoryIds"),
            new Document("$match", cat),
            new Document("$match", per),
            new Document("$match", type)
            ));

    for (Document dbObject : output) {
        System.out.println(dbObject.toJson());
    }

但是不幸的是没有得到想要的结果,有人可以建议如何在子文档中找到最相关的信息吗?

0 个答案:

没有答案