Spring data mongodb запрос добавить логическое поле, если значение существует в массиве - PullRequest
0 голосов
/ 15 сентября 2018

Я пытаюсь запросить некоторые данные из mongoDb, который содержит массив лайков.Каждый подобный объект содержит user.id из liker.

Мне нужно дополнительное поле boolean, в котором указано, нравится ли документ пользователю или нет.Поэтому мне нужно, чтобы isLiked было true, если пользователю понравился документ.

Вот что я сделал до сих пор:

Я использовал ConditionalOperators.Cond, чтобы проверить, если likes.userIdравен userId посетителя.

    @Override
public List<PostExtra> findPostsNearBy(double[] point, Distance distance, String thisUserId) {
    mongoTemplate.indexOps(CheckInEntity.class).ensureIndex(new GeospatialIndex("position"));

    ConditionalOperators.Cond conditionalOperators = new ConditionalOperators.ConditionalOperatorFactory(Criteria.where("likes.userId").is(thisUserId)).then(true).otherwise(false);


    Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.geoNear(
                    locationBasedOperationHelper.findNear(point,distance)
                        .query(new Query(privacyConsideredOperationHelper.privacyConsideredQuery(userRelationsEntity)))
                    ,"distance"
            ),
            //Aggregation.unwind("likes"),
            Aggregation.project("user", "description").and(conditionalOperators).as("isLiked")
    );

    final AggregationResults<PostExtra> results =
            mongoTemplate.aggregate(aggregation, PostEntity.class, PostExtra.class);
    return results.getMappedResults();
}

, если я удалю комментарий к Aggregation.unwind("likes"), я могу получать только сообщения, которые понравились этому пользователю, а не те, которые ему не понравились.

Я видел то же самое здесь , но я не знаю, с чем связан код MontoTemplate?Также я видел подходы с setIsSubset, все еще я не знаю реализацию java.

Я использую весеннюю загрузку 2.0.4.RELEASE и spring-boot-starter-data-mongodb.


@Document(collection = EntityCollectionNames.POST_COLLECTION_NAME)
public class PostEntity{
    @Id
    private String id;
    @Field
    @DBRef
    @Indexed
    private UserEntity user;

    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    @Field(value = "position")
    private Point position;

    @Field(value = "description")
    private String description;

    @Field
    private int likesCount;
    @Field
    private List<LikeEntity> likes;
}

ПостДополнительно:

public class PostExtra extends PostEntity {
    private double distance;
    private boolean isLiked;
}

Как:

public class LikeEntity {
    @Field
    private String userId;
}

1 Ответ

0 голосов
/ 15 сентября 2018

После некоторых поисков я обнаружил, что делать это без использования unwind Мне нужно реализовать что-то подобное для проецирования isLiked поля:

$cond:[
    {$gt:[
        {$size:
            {$setIntersection:["$likes.userId",userIdsToCheckIn]}
        },0]
    },true,false]

Я пытался сделать это весной так:

    ConditionalOperators.Cond conditionalOperators = new ConditionalOperators.ConditionalOperatorFactory(
            ComparisonOperators.Gt.valueOf(
                ArrayOperators.Size.lengthOfArray(
                        SetOperators.SetIntersection.arrayAsSet("$likes.userId").intersects(????????)
                )
            ).greaterThanValue(0)
    ).then(true).otherwise(false);

Но я не знал, что передать методу intersects(), и, видимо, Spring не позволяет передавать в качестве входных данных List или Array.Затем я обнаружил, что могу реализовать свой собственный AggregationExpressions и переопределить toDocument() метод.

Итак, я придумал это, и это сработало:

ConditionalOperators.Cond conditionalOperators = new ConditionalOperators.ConditionalOperatorFactory(
                new AggregationExpression() {
                    @Override
                    public Document toDocument(AggregationOperationContext aggregationOperationContext) {
                        return Document.parse("{$gt:[{$size:{$setIntersection:[\"$likes.userId\",[\""+userId+"\"]]}},0]}");
                    }
                }
        ).then(true).otherwise(false);

Конечно, я мог бы добавить $ condнепосредственно к реализации.


Я все еще хотел бы знать, существуют ли какие-либо пружинные решения, которые не содержат запросов mongodb непосредственно для этого.

...