膳食搭配智能平台

算法

智能推荐算法的实现与应用

智能推荐帖子算法是基于协同过滤算法实现的。

基于物品的协同过滤算法 : 给用户推荐与他之前喜欢的物品相似的物品

​ 我们通过定义了一张 user_Goods 表来存储用户 ,

基于用户的协同过滤算法 : 给用户推荐与他兴趣相似的用户喜欢的物品

余弦相似度算法

算法

编辑距离算法 、Jacquard相似度匹配算法和余弦相似度算法

对帖子和方案的标题进行使用 Elasticsearch 框架 中的 IK 分词 : 最细粒度划分

标签

素食、蛋奶、纯素、低卡、高蛋白、低脂、高纤维、高盐、健康、清真、绿色、

糖尿病

["素食", "烤鱼", "烤肉", "火锅", "海鲜"]

["甜点", "蛋糕", "面包", "冰淇淋", "巧克力"]

["早餐", "午餐", "晚餐", "夜宵", "零食"]

["酒", "红酒", "啤酒", "白酒", "葡萄酒"]

["健康饮食", "减肥", "饮食搭配", "营养均衡", "饮食习惯"]

["烹饪", "料理", "烘焙", "调味品", "厨具"]

["地方特色美食", "江浙菜", "川菜", "粤菜", "湘菜"]

["食材", "蔬菜", "水果", "肉类", "海鲜"]

["宵夜", "夜市美食", "街边小吃", "快餐", "烧烤"]

["饮品", "茶", "咖啡", "果汁", "饮料"]

分词(标签)

#分词器测试ik_max_word
POST _analyze
{
  "analyzer":"ik_max_word",
  "text":"我是中国人"
}
{
  "tokens" : [
    {
      "token" : "我",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "是",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "中国人",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "中国",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "国人",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 4
    }
  ]
}

编辑距离算法

计算两组最相似的标签

@Test
public void Test() {
    List<String> list1 = Arrays.asList("健康", "膳食", "减肥", "健美", "美食");
    List<String> list2 = Arrays.asList("美味", "特色", "减肥", "瘦身");
    int max = Math.max(list1.size(), list2.size());

    double similarity = minDistance(list1, list2);
    double distance = 1 - similarity / max;
    System.out.println(distance); // 0.19999999999999996

}
public static int minDistance(List<String> tagList1, List<String> tagList2) {
    int n = tagList1.size();
    int m = tagList2.size();

    if (n * m == 0) {
        return n + m;
    }

    int[][] d = new int[n + 1][m + 1];
    for (int i = 0; i < n + 1; i++) {
        d[i][0] = i;
    }

    for (int j = 0; j < m + 1; j++) {
        d[0][j] = j;
    }

    for (int i = 1; i < n + 1; i++) {
        for (int j = 1; j < m + 1; j++) {
            int left = d[i - 1][j] + 1;
            int down = d[i][j - 1] + 1;
            int left_down = d[i - 1][j - 1];
            if (!Objects.equals(tagList1.get    (i - 1), tagList2.get(j - 1))) {
                left_down += 1;
            }
            d[i][j] = Math.min(left, Math.min(down, left_down));
        }
    }
    return d[n][m];
}

余弦相似度

/**
 * 余弦相似度
 */
public class CosineSimilarityUtil {

    // 计算余弦相似度
    public static double cosineSimilarity(List<String> tag1, List<String> tag2) {
        // 将两个标签列表转换为向量
        Map<String, Integer> vector1 = getVector(tag1);
        Map<String, Integer> vector2 = getVector(tag2);

        // 计算两个向量的点积
        int dotProduct = 0;
        for (String key : vector1.keySet()) {
            if (vector2.containsKey(key)) {
                dotProduct += vector1.get(key) * vector2.get(key);
            }
        }

        // 计算两个向量的模长
        double magnitude1 = getMagnitude(vector1);
        double magnitude2 = getMagnitude(vector2);

        // 计算余弦相似度
        double cosineSimilarity = dotProduct / (magnitude1 * magnitude2);

        return cosineSimilarity;
    }

    // 将标签列表转换为向量
    public static Map<String, Integer> getVector(List<String> tags) {
        Map<String, Integer> vector = new HashMap<>();
        for (String tag : tags) {
            vector.put(tag, vector.getOrDefault(tag, 0) + 1);
        }
        return vector;
    }

    // 计算向量的模长
    public static double getMagnitude(Map<String, Integer> vector) {
        double magnitude = 0;
        for (int value : vector.values()) {
            magnitude += Math.pow(value, 2);
        }
        return Math.sqrt(magnitude);
    }
}

Jacquard相似度匹配算法

@Test
public static void Test() {
    List<String> list1 = Arrays.asList("健康", "膳食", "减肥", "健美", "美食");
    List<String> list2 = Arrays.asList("美味", "特色", "减肥", "瘦身");
    double similarity = calculateJacquardSimilarity(list1, list2);
    System.out.println(similarity); //0.125
}

/**
* Jacquard 相似度匹配
*
* @param list1
* @param list2
* @return
*/
public static double calculateJacquardSimilarity(List<String> list1, List<String> list2) {
    Set<String> set1 = new HashSet<>(list1);
    Set<String> set2 = new HashSet<>(list2);
    Set<String> intersection = new HashSet<>(set1);
    intersection.retainAll(set2);
    HashSet<String> strings = new HashSet<>(set1);
    strings.addAll(set2);
    return (double) intersection.size() / strings.size();
}

未来与展望

1 . 提供更优的搜索方式

目前

如今只是模糊搜索

下个版本

Elastic Stack

  • Elasticsearch 搜索引擎(重点)
  • Logstash 数据管道
  • Kibana 数据可视化

2 . 压力测试

目前

下个版本

通过 JMeter 更进一步的进行压力测试

3 . 在现有的项目中接入TensorFlow框架

目前

通过用户行为进行分析, 推荐热帖,热方案等

下个版本

加入基于物品、用户的协同过滤算法 :余弦相似度

加入基于帖子、方案中内容的推荐算法 : 基于内容的推荐算法是通过分析物品的属性和用户的历史偏好来预测用户可能喜欢哪些物品。

地图功能

需求分析

前端传省份来 , 在表balance_area和post_area中查数据

balance_area的字段 , post也是同理

​ id

​ balance_id 方案id

​ province 省份 area

​ create_Time

​ update_Time

​ is_Delete

将查到的balance_id封装成一个List , 再去调用写好的balance_food_relation查询方法

使用Mybatis-Plus的链式查询,只查询balance_id这个字段

List<Integer> balanceIds = new LambdaQueryChainWrapper<BalanceArea>(balanceAreaMapper)
        .eq(BalanceArea::getProvince, province)
        .list()
        .stream()
        .map(BalanceArea::getBalanceId)
        .collect(Collectors.toList());

请对这个功能优化一下,不用给出代码, 只需要在逻辑上等等方面进行优化 , 技术栈是SSM+SpringBoot+Mybatis-plus

系统关键技术

1. SpringBoot框架

Spring Boot 是 Spring 的一种全新的开发模式,它可以帮助开发者更快速地搭建 Java Web 应用,并提供许多自动化的配置,大大减少了项目的初始化和部署时间。

Spring Boot 框架的整体优点 :

  1. 简单快速:Spring Boot 的自动配置和约定大于配置的设计理念,可以帮助开发者更快速地创建项目并集成各种框架和服务。
  2. 开箱即用:Spring Boot 预置了常用的依赖和配置,可以帮助开发者省去很多初始化的工作。
  3. 多开发场景支持:Spring Boot 不仅可以用于 Web 开发,还可以支持多种开发场景,如批处理、消息队列、数据处理等。
  4. 可插拔架构:Spring Boot 架构采用模块化设计,开发者可以只使用需要的模块,同时也可以方便地添加和删除第三方模块。

2. SSM框架

1 . Spring框架

Spring 框架是一种轻量级的 Java 开发框架,它提供了一系列的框架和类库,可以帮助开发者构建复杂的企业级应用程序。Spring 框架的核心功能包括:IoC(Inversion of Control)容器、AOP(Aspect Oriented Programming)框架、数据访问和集成、Web 开发、测试和监控等。

Spring 框架的整体优点 :

  1. 易于使用和扩展:Spring 框架的一个主要优点是它非常容易学习和使用。它具有许多类库和插件,可以快速实现复杂的业务逻辑,并可以方便地进行模块化开发和组件化重用。
  2. 提高代码的可测试性:Spring 框架的依赖注入(DI)和面向切面编程(AOP)特性,可以帮助开发人员将应用程序中的业务逻辑与非业务逻辑分离,从而提高代码的可测试性。
  3. 增加应用程序的灵活性和可拓展性:Spring 框架可以帮助开发者实现应用程序的可插拔性和可扩展性。因为开发人员可以将不同的模块通过轻松的组装与集成来构建一个更加强大、可定制的应用程序。
  4. 促进企业级应用程序的开发和部署:Spring 框架可以帮助企业级应用程序快速且可靠地实现各种业务需求,同时提供了丰富的工具和类库,方便应用程序的部署和运行。

2 . SpringMvc框架

Spring MVC 框架是基于 Model-View-Controller(MVC)设计模式的一种框架。它可以帮助开发者实现 Web 应用程序的开发和部署,提供了一种简单而灵活的方式来处理 HTTP 请求和响应。

Spring MVC 框架的整体优点 :

  1. 简单易用:Spring MVC 框架的 API 简单易用,开发者可以快速上手并进行开发。
  2. 灵活性强:可以自由选择各种框架比如 JSP、Thymeleaf、FreeMarker 作为视图模板技术,并且可以支持 RESTful 风格,使其更加灵活。
  3. 解耦合:Spring MVC 框架采用了分离 MVC 的思路,使得 Controller、View、Model 可以独立进行开发和维护,从而达到解耦合的效果。
  4. 可测试性强:Spring MVC 框架的请求和响应处理、MVC 拦截器等功能都是基于接口的,这意味着整个应用程序的单元测试和集成测试可以更容易地进行。
  5. 可扩展性强:Spring MVC 框架提供了丰富的扩展点,比如拦截器、视图解析器、处理器映射器等,使得开发者可以自由扩展框架的功能。

3 . Mybatis框架

MyBatis是一个开源的持久层框架,它支持自定义SQL、存储过程和高级映射。使用其可以避免很多JDBC的重复代码和样板式代码。其作为一种简单、灵活、高效的ORM框架得到了广泛的应用和推广,对于需要进行复杂查询和业务逻辑处理的项目,使用MyBatis可以极大地提高开发效率和代码的可维护性。

Mybatis 框架的整体优点 :

  1. 灵活而强大:MyBatis支持各种不同的数据库操作方法,例如通过XML或注解定义映射、支持动态SQL,满足了不同类型的数据库操作需求。
  2. 性能好:MyBatis可以通过多种配置方式进行SQL语句的优化和缓存,能够提高程序的性能和稳定性。
  3. 易于测试:MyBatis可以在测试环境中快速方便地进行单元测试,也方便进行数据的回滚操作。
  4. 可扩展性强:MyBatis提供了插件的机制,可以通过自定义插件来扩展MyBatis的功能,也可以自定义类型转换器、错误处理等。

3 . SpringSecurity框架

Spring Security是Spring的安全框架,它提供了全面而灵活的安全性,支持多种身份验证和授权机制,助力开发者构建安全可靠的Web应用程序。

Spring Security的核心原理是在Spring框架上附加一个安全层,通过过滤器来处理请求,从而实现对Web应用程序的保护。接下来我们将详细介绍Spring Security的核心组件和优点。

Spring Security 框架的整体优点 :

  1. 高度可定制:通过Spring Security框架提供的多种配置选项,可以实现对Web应用程序的高度定制,从而满足特定的安全性需求。
  2. 多种身份验证和授权机制:Spring Security框架支持多种身份验证和授权机制,如基于表单的认证、基于http基本认证、基于用户证书验证等。
  3. 安全性高:通过过滤器实现用户身份认证和请求过滤,在确保应用程序可用性的同时,保证了应用程序的安全性。
  4. 容易集成:Spring Security框架与Spring框架天然的结合在一起,可方便地集成到现有的Spring应用程序中。
  5. 多种加密方式:Spring Security框架提供了多种加密认证方式,包括MD5、SHA、BCrypt等,支持普通密码和密码加盐等模式。

4 . Redis框架

Redis是一个开源的高性能、非关系型的内存数据结构存储系统,它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,同时也提供了一些高级功能,如事务、发布/订阅、Lua脚本等,可广泛应用于缓存、消息队列、计数器、实时排行榜等场景。

Redis 框架的整体优点 :

  1. 高性能:Redis的数据存储在内存中,读写速度非常快,而且支持多线程访问,保证了高并发访问时的性能。
  2. 可扩展性好:Redis可以很方便地扩展到多个节点,实现数据的分布式存储和高可用性。
  3. 数据结构多样化:Redis支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,适合不同类型的数据存储和管理。
  4. 丰富的功能:Redis提供了丰富的功能,如事务、发布/订阅、Lua脚本等,方便应用程序的开发和运维。
  5. 易于使用和管理:Redis的命令简单易懂,同时提供了良好的客户端接口和管理工具,方便使用和管理。

需求分析

膳食小搭项目需要实现用户上传文件、用户论坛发帖、食物功能以及基于编辑距离算法、Jacquard相似度匹配算法和余弦相似度算法实现推荐系统等功能。

  1. 用户上传文件:包括用户上传各种图片格式的食物图片,以及文件的存储、管理、查询和分类等功能。
  2. 用户论坛发帖:用户可以在论坛中发布相关饮食话题,包括帖子的创建、浏览、回复和管理等功能。
  3. 食物功能:包括对食物信息的管理,如食材名、营养信息、图片等,以及根据食材的营养信息计算营养价值和推荐合理搭配。
  4. 推荐系统:根据精确的算法,在数据库中处理用户消费和购物车中的商品信息,为每个用户定制精准的推荐方案。

系统设计思想

  1. 数据层:使用MySQL作为主要的关系型数据库,用于存储用户个人信息、帖子内容等,同时使用Redis作为缓存,加快食物信息的查询速度。
  2. 业务逻辑层:采用Spring和Spring Boot框架实现业务逻辑,包括用户身份验证、食物信息处理、推荐算法处理等。
  3. 表示层:使用Spring MVC框架实现前台页面和后台管理页面,包括用户注册、登录、个人信息管理、食谱推荐等。
  4. 用户论坛发帖功能:使用Spring MVC框架实现论坛页面的开发,采用Java EE中的后端技术实现。
  5. 食物功能:使用Redis缓存和MySQL数据库存储食品信息,采用Spring Boot框架实现食品信息的查询、计算营养值、搭配推荐等功能。
  6. 推荐系统:基于编辑距离算法、Jacquard相似度匹配算法和余弦相似度算法实现推荐系统的关键算法,使用Hadoop和Spark等大数据技术存储和处理用户数据,向用户提供个性化推荐服务。
  7. 系统安全:采用Spring Security和JWT实现用户身份验证和授权功能,防止攻击者获取非法访问权限。

详细设计

数据层设计

  1. 用户表:用于存储用户的基本信息,如用户名、密码、邮箱、手机号等。
  2. 方案表:用于存储方案的基本信息,如方案名、方案描述、创建者等。
  3. 帖子表:用于存储帖子的基本信息,包括标题、内容、作者等。
  4. 地图表:用于存储人数分布地图的信息,包括地区、人数等。
  5. 轮播图表:用于存储轮播图的基本信息,包括图片、标题、链接等。
  6. 食物表:用于存储食物的基本信息,包括食物名称、食材、营养成分等。

业务层设计

  1. 用户管理:采用SpringSecurity和JWT等框架实现用户身份验证和授权,保障用户信息安全。同时,在业务层中实现用户的注册、登录、个人信息管理等功能。
  2. 文件上传:采用上传组件hutools来实现文件上传功能,同时使用私有图床系统来存储用户上传的图片、文件等数据。
  3. 论坛功能:采用Spring Boot框架实现论坛页面的开发,使用Java EE中的后端技术实现帖子的创建、浏览、回帖等功能。
  4. 食物功能:采用Redis缓存和MySQL数据库存储食物信息,使用SpringBoot框架实现食物信息的查询、计算营养值、搭配推荐等功能,同时使用Gson等框架对JSON数据进行处理和解析。
  5. 推荐系统设计:基于编辑距离算法、Jacquard相似度匹配算法和余弦相似度算法实现推荐系统的关键算法,向用户提供个性化推荐服务。

表示层设计

  1. 接口(API):前端请求数据的接口,后端返回数据的接口。接口主要分为三种类型:

    • CRUD(create、read、update、delete)接口:用于对数据库中数据进行增删改查操作,如食物列表、食物详情等接口。
    • 用户认证与授权接口:用于用户登录、注册、重置密码等操作。
    • 业务逻辑接口:自定义的业务相关接口。比如,根据用户的身体情况和营养需求,返回符合条件的膳食配餐方案等。
  2. 控制器(Controller):连接视图和接口,负责请求的处理。主要包括以下功能:

    • 接受并解析请求参数,对请求进行验证和过滤。
    • 调用模型层处理数据,根据业务逻辑生成响应数据。
    • 对响应数据进行封装,输出给客户端。
    • 除此之外,控制器还可包括一些常用的功能模块,如认证模块、权限验证模块等。
  3. 模型(Model):连接数据库层,负责数据的存储和处理。主要包括以下功能:

    • 定义数据库表结构,提供对表的增删改查等操作。
    • 根据业务需求,实现一些复杂的查询和计算逻辑,如膳食计算等。
    • 对外提供API接口,供上层控制器调用。
最后修改:2023 年 09 月 13 日
如果觉得我的文章对你有用,请随意赞赏