Shopify API gem中Customer.search与Customer.find的差异疑问
我需要获取所有购买过我司“foobar”产品的客户邮箱地址。最初我使用以下代码,运行结果正常:
Customer.search(query: "state:enabled").each do |c| c.orders.map do |o| o.line_items.each do |i| t = i.title p c.email if t.include?("foobar") end end end
随后我尝试了另一组代码,原以为与前者等效,但仅得到前者结果的子集:
Customer.find(:all, params:{state:"enabled"}).each do |c| c.orders.map do |o| o.line_items.each do |i| t = i.title p c.email if t.include?("foobar") end end end
我的问题是:对应/admin/customers/search.json端点的Customer.search(...)与Customer.find(:all, ...)之间有什么差异?
补充说明:购买“foobar”产品的客户超过50位(默认返回条数限制),若两者无差异,查询结果应一致,难道我的猜测有误?
解答
这两个方法的核心差异在于数据获取的方式和分页处理逻辑,刚好命中了你提到的“超过50条”这个关键点:
Customer.search的行为
这个方法是对接/admin/customers/search.json端点的,它会自动处理分页逻辑——默认会遍历所有符合条件的客户(即使总数超过50条)。后台会自动请求多页数据,把所有满足state:enabled的客户都拉取回来,不会被默认的50条限制卡住。它的查询逻辑基于Shopify的搜索API,天然支持全量搜索遍历。Customer.find(:all, params:{state:"enabled"})的行为
这个方法是传统的ActiveRecord风格查询,但在Shopify的API语境下,它默认只会返回第一页的数据(最多50条)。如果你没有手动指定分页参数(比如limit和page),它不会自动拉取后续页面的内容,所以你只能拿到前50个符合条件的客户,自然就只能得到前者结果的子集。另外,find(:all)这种写法在很多现代ORM里已经被标记为过时,推荐写法是Customer.all,但核心问题还是分页处理的差异。验证你的猜测
你的猜测完全正确!正是因为购买“foobar”的客户超过了50位,Customer.find(:all)只返回了第一页的客户,而Customer.search则遍历了所有页面的客户,才导致结果数量不同。如果客户总数少于50,你会发现两个方法的结果是一致的。
如果想让Customer.find也返回全量数据,你需要手动处理分页,比如循环请求每一页直到没有更多数据:
page = 1 loop do customers = Customer.find(:all, params: { state: "enabled", page: page, limit: 250 }) # 最大limit为250 break if customers.empty? customers.each do |c| c.orders.map do |o| o.line_items.each do |i| t = i.title p c.email if t.include?("foobar") end end end page += 1 end
不过更省心的方式还是用Customer.search,它已经帮你封装了全量遍历的逻辑,不需要手动处理分页。
内容的提问来源于stack exchange,提问作者keiichiro shikano

