商品搜索。

1. 导入商品数据

1.1. 搭建搜索工程

pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu</groupId>
        <artifactId>gmall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.atguigu</groupId>
    <artifactId>gmall-search</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gmall-search</name>
    <description>谷粒商城搜索系统</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.atguigu</groupId>
            <artifactId>gmall-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

bootstrap.yml:

spring:
  application:
    name: search-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848

application.yml:

server:
  port: 18086
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
  zipkin:
    base-url: http://localhost:9411
    discovery-client-enabled: false
    sender:
      type: web
  sleuth:
    sampler:
      probability: 1
  elasticsearch:
    rest:
      uris: http://172.16.116.100:9200
feign:
  sentinel:
    enabled: true
logging:
  level:
    com.atguigu.gmall: debug

GmallSearchApplication.java引导类:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class GmallSearchApplication {
   

    public static void main(String[] args) {
   
        SpringApplication.run(GmallSearchApplication.class, args);
    }

}

网关路由:

        - id: search-route
          uri: lb://search-service
          predicates:
            - Host=search.gmall.com

1.2. 构建es数据模型

接下来,我们需要商品数据导入索引库,便于用户搜索。

那么问题来了,我们有SPU和SKU,到底如何保存到索引库?

先看京东搜索,输入“小米”搜索:

可以看到每条记录就是一个sku,再来看看每条记录需要哪些字段:

直观能看到:sku的默认图片、sku的价格、标题、skuId

排序及筛选字段:综合、新品、销量、价格、库存(是否有货)等

聚合字段:品牌、分类、搜索规格参数(多个)

最终可以构建一个Goods对象:(注意属性名需要提前和前端约定好,不能随便改)

@Document(indexName = "goods", type = "info", shards = 3, replicas = 2)
@Data
public class Goods {
   

    @Id
    private Long skuId;
    @Field(type = FieldType.Keyword, index = false)
    private String pic;
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;
    @Field(type = FieldType.Double)
    private Double price;
    
    @Field(type = FieldType.Long)
    private Long sales; // 销量

    @Field(type = FieldType.Boolean)
    private Boolean store; // 是否有货

    @Field(type = FieldType.Date)
    private Date createTime; // 新品
    
    @Field(type = FieldType.Long)
    private Long brandId;
    @Field(type = FieldType.Keyword)
    private String brandName;
    @Field(type = FieldType.Long)
    private Long categoryId;
    @Field(type = FieldType.Keyword)
    private String categoryName;
    @Field(type = FieldType.Nested)
    private List<SearchAttrValue> attrs;

}

搜索规格参数:SearchAttrValue

@Data
public class SearchAttrValue {
   

    @Field(type = FieldType.Long)
    private Long attrId;
    @Field(type = FieldType.Keyword)
    private String attrName;
    @Field(type = FieldType.Keyword)
    private String attrValue;
}

“type”: “nested”

嵌套结构,防止数据扁平化问题。

参照官方文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-objects.html

1.3. 批量导入

1.3.1. 数据接口

索引库中的数据来自于数据库,我们不能直接去查询商品的数据库,因为真实开发中,每个微服务都是相互独立的,包括数据库也是一样。所以我们只能调用商品微服务提供的接口服务。

先思考我们需要的数据:

  • 分页查询已上架的SPU信息
  • 根据SpuId查询对应的SKU信息(接口已写好)
  • 根据分类id查询商品分类(逆向工程已自动生成)
  • 根据品牌id查询品牌(逆向工程已自动生成)
  • 根据skuid查询库存(gmall-wms中接口已写好)
  • 根据spuId查询检索规格参数及值
  • 根据skuId查询检索规格参数及值

大部分接口之前已经编写完成,接下来开发接口:

1.3.1.1. 分页查询已上架SPU

在gmall-pms的SpuController中添加方法:

@PostMapping("page")
public ResponseVo<List<SpuEntity>> querySpusByPage(@RequestBody PageParamVo pageParamVo){
   
    PageResultVo page = spuService.queryPage(pageParamVo);
    List<SpuEntity> list = (List<SpuEntity>)page.getList();
    return ResponseVo.ok(list);
}
1.3.1.2. 根据spuId查询检索属性及值

在gmall-pms的SpuAttrValueController中添加方法:

@ApiOperation("根据spuId查询检索属性及值")
@GetMapping("spu/{spuId}")
public ResponseVo<List<SpuAttrValueEntity>> querySearchAttrValueBySpuId(@PathVariable("spuId")Long spuId){
   
    List<SpuAttrValueEntity> attrValueEntities = spuAttrValueService.querySearchAttrValueBySpuId(spuId);

    return ResponseVo.ok(attrValueEntities);
}

在SpuAttrValueService中添加接口方法:

List<SpuAttrValueEntity> querySearchAttrValueBySpuId(Long spuId);

在实现类SpuAttrValueServiceImpl中添加实现方法:

@Autowired
private SpuAttrValueMapper spuAttrValueMapper;

@Override
public List<SpuAttrValueEntity> querySearchAttrValueBySpuId(Long spuId) {
   

    return this.spuAttrValueMapper.querySearchAttrValueBySpuId(spuId);
}

在SpuAttrValueMapper接口中添加接口方法:

@Mapper
public interface SpuAttrValueMapper extends BaseMapper<SpuAttrValueEntity> {
   

    List<SpuAttrValueEntity> querySearchAttrValueBySpuId(Long spuId);
}

在SpuAttrValueMapper对应的映射文件中添加配置:

<select id="querySearchAttrValueBySpuId" resultType="SpuAttrValueEntity">
    select a.id,a.attr_id,a.attr_name,a.attr_value,a.spu_id
    from pms_spu_attr_value a INNER JOIN pms_attr b on a.attr_id=b.id
    where a.spu_id=#{spuId} and b.search_type=1
</select>
1.3.1.3. 根据skuId查询检索属性及值

在gmall-pms的SkuAttrValueController中添加方法:

@ApiOperation("根据spuId查询检索属性及值")
@GetMapping("sku/{skuId}")
public ResponseVo<List<SkuAttrValueEntity>> querySearchAttrValueBySkuId(@PathVariable("skuId")Long skuId){
   
    List<SkuAttrValueEntity> attrValueEntities = skuAttrValueService.querySearchAttrValueBySkuId(skuId);

    return ResponseVo.ok(attrValueEntities);
}

在SkuAttrValueService中添加接口方法:

List<SkuAttrValueEntity> querySearchAttrValueBySkuId(Long skuId);

在实现类SkuAttrValueServiceImpl中添加实现方法:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个比较广泛的问题,因为实现商品搜索界面的代码可能因应用程序的不同而异。我可以给出一个通用的搜索界面代码的示例,并对其中的一些关键部分进行解释。 示例代码: ```java public class SearchActivity extends AppCompatActivity { private EditText mSearchEditText; private Button mSearchButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search); mSearchEditText = findViewById(R.id.search_edittext); mSearchButton = findViewById(R.id.search_button); mSearchButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String query = mSearchEditText.getText().toString().trim(); if (!TextUtils.isEmpty(query)) { startSearch(query); } } }); } private void startSearch(String query) { // 实现搜索逻辑的代码 // ... // 搜索完成后,跳转到结果页面并传递搜索关键词 Intent intent = new Intent(this, SearchResultActivity.class); intent.putExtra("query", query); startActivity(intent); } } ``` 上述代码中,`SearchActivity` 是搜索界面的主活动,其中包含一个用于输入搜索关键字的文本框 `mSearchEditText` 和一个用于启动搜索的按钮 `mSearchButton`。在 `onCreate` 方法中,我们通过调用 `findViewById` 方法获取这两个控件的实例,并为按钮设置了一个点击监听器。当用户点击按钮时,监听器会获取文本框中的搜索关键字并调用 `startSearch` 方法开始执行搜索逻辑。 `startSearch` 方法是我们需要实现的搜索逻辑的地方。这里只是一个示例,实际中可能需要连接到服务器或本地数据库来进行搜索。一旦搜索完成,我们可以创建一个新的 `Intent` 对象,并使用 `putExtra` 方法将搜索关键字作为字符串传递给搜索结果页面。最后,我们调用 `startActivity` 方法来启动结果页面。 当用户点击搜索按钮时,搜索逻辑将会在后台运行,而不会阻塞主线程。这是因为我们使用了 `OnClickListener` 接口的回调函数,它在单独的线程中执行。这样,即使搜索需要一些时间,用户仍然可以在搜索期间继续使用应用程序的其他功能。 此外,我们还需要使用一个布局文件来定义搜索界面的外观。这个布局文件应该包含一个文本框和一个按钮,以及任何其他的用户界面元素,例如标签或图标。在示例代码中,我们使用了一个名为 `activity_search.xml` 的布局文件,其中包含以下内容: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/search_edittext" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/search_hint" android:imeOptions="action_search" android:inputType="text" android:maxLines="1" /> <Button android:id="@+id/search_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:text="@string/search_button_text" /> </RelativeLayout> ``` 这个布局文件定义了一个相对布局,其中包含一个文本框和一个按钮。文本框使用 `EditText` 元素来定义,它具有一些特殊属性,例如 `hint` 属性用于显示在文本框中的提示文本,`imeOptions` 属性用于在软键盘上显示搜索按钮,`inputType` 属性用于指定输入的数据类型,以及 `maxLines` 属性用于限制文本框中的行数。按钮使用 `Button` 元素来定义,并具有一个 `android:text` 属性,用于设置按钮上显示的文本。 以上是一个简单的 Android 应用程序搜索界面的示例代码及其解释。当然,在实际开发中,还有许多其他的考虑因素,例如如何处理搜索结果、如何进行搜索结果的排序、如何实现自动完成等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值