ট্যাগ ব্যবহার করে রিলেটেড পোস্ট বের করা - স্প্রিং হাইবারনেট

postrelatedspring-datatag

সতর্কতা: ট্যাগ দিয়ে রিলেটেড পোস্ট বের করার এই কোড মাত্রই ডেভেলপ করলাম, এই ব্যাপারে আমার কোন পূর্বের অভিজ্ঞতা ছিলোনা। আমার এখনো এর উপর কনফিডেন্স তৈরী হয় নাই। তাই প্রোডাকশনে ব্যবহার করার আগে আরেকবার ভেবে নিতে হবে। আর এর থেকে ভালো বুদ্বি কারো মাথায় আসলে প্লিজ জানাবেন।


রিলেটেড পোস্ট/আর্টিকেল বের করার জন্য ইলাস্টিক বা সোলার ব্যবহার করা যায়। আমি চাচ্ছিলাম কোন ইন্ডেক্সার ব্যবহার না করে ট্যাগ দিয়ে রিলেটেড পোস্ট বের করার। কারণ আমার এখানে রিলেটেড এর ব্যবহার খুব সাধারণ, তাই কামান নিয়ে আসতে চাচ্ছিলাম না।


পরিকল্পনা:

১. প্রতিটা পোস্টে একাধিক ট্যাগ সংযুক্ত করা যাবে।

২. যে পোস্ট এখন পড়ছি তার সবগুলা ট্যাগ নিয়ে সার্চ করবো অন্য পোস্টের মধ্যে

৩. যে সব পোস্টে এক বা একাধিক ট্যাগের মিল পাওয়া যাবে, তাদেরকে তুলে আনবো

৪. সবচেয়ে বেশি ট্যাগ মিল আছে এমন দুটা পোস্ট রিলেটেড পোস্ট হিসাবে ফেতর পাঠানো


পরিকল্পনা শেষ, এখন কোড করার পালা।


JPA কোয়েরি

@Query("SELECT p FROM Post p " +
        "LEFT JOIN p.tags t  " +
        "WHERE t.id IN ?1 AND p.id <> ?2 ")
Set<PostProjection> findPostByTag(List<String> tagIds, String originalPostId);

PostRepository


সার্ভিস

@Override
@Transactional
public Set<PostProjection> findRelatedPost(String postId) {
    Post originalPost = findById(postId);
    List<String> originalTagIds = originalPost.getTags()
            .stream()
            .map(tag -> tag.getId())
            .collect(Collectors.toList());

    return relatedPostMap(originalPost, originalTagIds).entrySet()
            .stream()
            .limit(2)
            .map(relatedPostMap -> relatedPostMap.getValue())
            .collect(Collectors.toSet());
}

private Map<Integer, PostProjection> relatedPostMap(Post originalPost, List<String> originalTagIds) {
    Set<PostProjection> posts = findRelatedPost(originalPost, originalTagIds);
    Map<Integer, PostProjection> map = new TreeMap<>((Comparator<Integer>) (o1, o2) -> o2.compareTo(o1));

    for (PostProjection post : posts) {
        List<String> tagIds = post.getTags()
                .stream()
                .map(t -> t.getId())
                .collect(Collectors.toList());

        tagIds.retainAll(originalTagIds);
        map.put(tagIds.size(), post);
    }
    return map;
}

private Set<PostProjection> findRelatedPost(Post originalPost, List<String> originalTagIds) {
    return postRepository.findPostByTag(originalTagIds, originalPost.getId());
}

PostServiceImpl


কন্ট্রোলার (PostApi)

@GetMapping("/{postId}/related-post")
public ResponseEntity findRelatedPosts(@PathVariable String postId){
    return ResponseEntity.ok()
            .body(postService.findRelatedPost(postId));
}



ধন্যবাদ