从零开始:用Swift和Milvus构建数据分析应用

云信安装大师
90
AI 质量分
11 5 月, 2025
4 分钟阅读
0 阅读

从零开始:用Swift和Milvus构建数据分析应用

引言

在当今数据驱动的时代,构建高效的数据分析应用变得越来越重要。本文将带你从零开始,使用Swift编程语言和Milvus向量数据库构建一个简单的数据分析应用。我们将创建一个能够存储、索引和查询向量数据的完整解决方案。

准备工作

环境要求

  1. macOS系统(推荐10.15+)
  2. Xcode 12+
  3. Swift 5.3+
  4. Milvus单机版(本文使用v2.0)

安装依赖

首先确保你已经安装了Homebrew,然后安装Milvus:

代码片段
# 安装Homebrew(如果尚未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 使用Homebrew安装Milvus
brew install milvus

启动Milvus服务:

代码片段
milvus run

项目设置

  1. 打开Xcode,创建新项目
  2. 选择”App”模板
  3. 输入产品名称:”DataAnalysisWithMilvus”
  4. 语言选择Swift,界面选择SwiftUI
  5. 创建完成后,添加Milvus Swift SDK依赖

在Package.swift中添加依赖:

代码片段
dependencies: [
    .package(url: "https://github.com/milvus-io/milvus-sdk-swift.git", from: "0.1.0")
]

Milvus基础操作

连接Milvus数据库

首先创建一个MilvusService.swift文件来处理所有数据库操作:

代码片段
import Foundation
import MilvusSwift

class MilvusService {
    static let shared = MilvusService()
    private var client: MilvusClient?

    private init() {
        setupClient()
    }

    private func setupClient() {
        // 连接到本地Milvus实例
        let config = MilvusClientConfig(
            host: "localhost",
            port: 19530,
            timeout: 10
        )

        do {
            client = try MilvusClient(config: config)
            print("成功连接到Milvus服务器")
        } catch {
            print("连接失败: \(error.localizedDescription)")
        }
    }

    // ...其他方法将在下面添加...
}

创建集合(Collection)

在数据分析应用中,集合相当于传统数据库中的表。让我们创建一个用于存储产品特征的集合:

代码片段
extension MilvusService {
    func createProductCollection() throws {
        guard let client = client else {
            throw NSError(domain: "MilvusError", code: -1, userInfo: [NSLocalizedDescriptionKey: "客户端未初始化"])
        }

        // 定义集合schema
        let schema = CollectionSchema(
            name: "products",
            description: "产品特征向量集合",
            autoID: false,
            fields: [
                // ID字段(主键)
                FieldSchema(name: "product_id", dataType: .int64, isPrimaryKey: true),

                // 特征向量字段(128维浮点向量)
                FieldSchema(name: "feature_vector", dataType: .floatVector, dim: 128),

                // 产品名称字段
                FieldSchema(name: "product_name", dataType: .string),

                // 价格字段
                FieldSchema(name: "price", dataType: .float)
            ]
        )

        // 创建索引参数
        let indexParams = IndexParameters(
            fieldName: "feature_vector",
            indexType: .ivfFlat,
            metricType: .l2,
            params: ["nlist": "128"]
        )

        try client.createCollection(schema)
        try client.createIndex(onCollectionNamed: "products", parameters: indexParams)

        print("成功创建产品和索引")
    }
}

SwiftUI界面实现

现在让我们创建一个简单的界面来展示我们的数据分析功能。

主界面视图

代码片段
import SwiftUI

struct ContentView: View {
    @State private var searchText = ""
    @State private var searchResults = [Product]()

    var body: some View {
        NavigationView {
            VStack {
                SearchBar(text: $searchText, onSearchButtonClicked: searchProducts)
                    .padding()

                List(searchResults, id: \.id) { product in
                    ProductRow(product: product)
                }

                Spacer()

                Button(action: insertSampleData) {
                    Text("插入测试数据")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(8)
                }
                .padding()
            }
            .navigationTitle("产品分析")
        }
    }

    func searchProducts() {
        Task {
            do {
                let results = try await MilvusService.shared.searchProducts(queryText: searchText)
                DispatchQueue.main.async {
                    self.searchResults = results
                }
            } catch {
                print("搜索错误:", error.localizedDescription)
            }
        }
    }

    func insertSampleData() {
        Task { 
            try await MilvusService.shared.insertSampleProducts()
        }
    }
}

struct ProductRow: View {
    let product: Product

    var body some View { 
        HStack { 
            VStack(alignment:.leading) { 
                Text(product.name).font(.headline)
                Text("$\(product.price, specifier:"%.2f")").font(.subheadline) 
            } 

           Spacer() 

           Text("相似度:\(product.similarity *100, specifier:"%.1f")%") 
               .font(.caption) 
               .foregroundColor(.gray) 
       } 
   } 
} 

struct SearchBar : UIViewRepresentable {  
   @Binding var text : String  
   var onSearchButtonClicked : () -> Void  

   func makeCoordinator() -> Coordinator {  
       return Coordinator(text:$text, onSearchButtonClicked : onSearchButtonClicked)  
   }  

   func makeUIView(context : Context) -> UISearchBar {  
       let searchBar=UISearchBar(frame:.zero)  
       searchBar.delegate=context.coordinator  
       return searchBar  
   }  

   func updateUIView(_ uiView : UISearchBar , context : Context){  
       uiView.text=text  
   }  

   class Coordinator : NSObject , UISearchBarDelegate{  
       @Binding var text:String  
       var onSearchButtonClicked : () -> Void  

       init(text : Binding<String> , onSearchButtonClicked:@escaping()->Void){  
           _text=text  
           self.onSearchButtonClicked=onSearchButtonClicked  
       }  

       func searchBar(_ searchBar : UISearchBar , textDidChange searchText:String){  
           text=searchText  

           if text.isEmpty{ onSearchButtonClicked()}  

       }  

       func searchBarSearchButtonClicked(_ searchBar : UISearchBar){onSearchButtonClicked()}  

   }  

} 

struct ContentView_Previews : PreviewProvider{static var previews=some View{ContentView()}} 

数据模型与业务逻辑

定义产品模型

代码片段

struct Product : Identifiable , Codable{let id : Int64let name:Stringlet price:Floatsimilarity:Float} 

实现核心业务方法

MilvusService中添加以下方法:

代码片段

extension Milvu s Service{//插入示例数据func insertSampleProducts()async throws{guard let client=client else{throw NSError(domain:"Milvu s Error",code:-1)}//生成随机特征向量func randomFeatureVector()->[Float]{return(0..<128).map{_ in Float.random(in:-1...1)}}//示例产品数据let sampleProducts=[("iPhone13",999.99),("MacBookPro",1999.99),("AirPods Pro",249.99),("iPad Air",599.99),("Apple Watch Series7",399.99)]//准备插入数据var entities=[InsertRequest.Entity]()for(index,(name,price))in sampleProducts.enumerated(){entities.append(InsertRequest.Entity(fieldName:"product_id",fieldValue:.int64Value(Int64(index))))entities.append(InsertRequest.Entity(fieldName:"feature_vector",fieldValue:.floatVectorValue(randomFeatureVector())))entities.append(InsertRequest.Entity(fieldName:"product_name",fieldValue:.stringValue(name)))entities.append(InsertRequest.Entity(fieldName:"price",fieldValue:.floatValue(Float(price))))}let request=InsertRequest(collectionName:"products",entities:[entities])try client.insert(request)//刷新使新数据可搜索try client.flush(collectionsNames["products"])print("成功插入\(sampleProducts.count)个产品")}//搜索相似产品func searchProducts(queryText:String)async throws->[Product]{guard let client=client else{throw NSError(domain:"Milvu s Error",code:-1)}//在实际应用中,这里应该将queryText转换为特征向量//为简单起见,我们使用随机向量作为查询let queryVector=(0..<128).map{_ in Float.random(in:-1...1)}let searchParams=["nprobe":"16"]let request=SearchRequest(collectionName:"products","feature_vector":queryVector],params.searchParams,limit10)//执行搜索let response.try await client.search(request)//处理结果var products=[Product]()for result in response.results{var productId.Int64?var productName.String?var price.Float?for field in result.fields{if case let.int64Value(value)=field.value where field.name=="product_id"{productId=value}else if case let.stringValue(value)=field.value where field.name=="product_name"{productName=value}else if case let.floatValue(value)=field.value where field.name=="price"{price=value}}if let id.productId,name.productName.price.price{products.append(Product(id:id,name.name.price.price.similarity.result.distance))}}return products}} 

运行与测试

1.构建并运行Xcode项目2点击”插入测试数据”按钮加载示例数据3在搜索栏中输入查询内容4查看返回的相似产品列表

总结与注意事项

通过本教程我们完成了:-搭建了基于Swift和Milvu s的数据分析应用-实现了数据的存储和相似性搜索功能-创建了用户友好的SwiftUI界面

注意事项:1.Milvu s服务必须保持运行状态2在生产环境中应考虑更复杂的特征提取方法3对于大规模数据集应考虑使用集群版Milvu s4定期优化索引参数以获得最佳性能5注意内存管理特别是处理大量向量时6考虑添加错误处理和加载状态显示以改善用户体验7在生产环境中应实现更安全的连接方式而非本地明文配置8定期备份重要数据9监控系统性能及时调整资源分配10考虑添加缓存机制减少重复计算

原创 高质量