복붙노트

[RUBY-ON-RAILS] 액티브 레코드를 사용하여 직렬화 된 데이터를 검색

RUBY-ON-RAILS

액티브 레코드를 사용하여 직렬화 된 데이터를 검색

나는이 작업을 수행 어떻게, 직렬화 된 컬럼의 간단한 쿼리를 할 노력하고있어?

serialize :mycode, Array


1.9.3p125 :026 > MyModel.find(104).mycode
  MyModel Load (0.6ms)  SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`id` = 104 LIMIT 1
 => [43565, 43402] 
1.9.3p125 :027 > MyModel.find_all_by_mycode("[43402]")
  MyModel Load (0.7ms)  SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = '[43402]'
 => [] 
1.9.3p125 :028 > MyModel.find_all_by_mycode(43402)
  MyModel Load (1.2ms)  SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` = 43402
 => [] 
1.9.3p125 :029 > MyModel.find_all_by_mycode([43565, 43402])
  MyModel Load (1.1ms)  SELECT `mymodels`.* FROM `mymodels` WHERE `mymodels`.`mycode` IN (43565, 43402)
 => [] 

해결법

  1. ==============================

    1.기본적으로, 당신은 할 수 없습니다. #serialize의 단점은 데이터베이스의 기본 추상화를 무시하고 있다는 점이다. 당신은 꽤 많이로드 및 데이터를 저장으로 제한하고 있습니다.

    기본적으로, 당신은 할 수 없습니다. #serialize의 단점은 데이터베이스의 기본 추상화를 무시하고 있다는 점이다. 당신은 꽤 많이로드 및 데이터를 저장으로 제한하고 있습니다.

    그것은 될 수있는 기어에 응용 프로그램을 느리게하는 일이 매우 좋은 방법 말했다 :

    MyModel.all.select { |m| m.mycode.include? 43402 }
    

    이야기의 도덕적 : 당신은 쿼리에 필요한 모든 데이터를 #serialize를 사용하지 않습니다.

  2. ==============================

    2.그것은 당신의 응용 프로그램을 느리게하지 그냥 트릭입니다. 당신은 .to_yaml 사용해야합니다.

    그것은 당신의 응용 프로그램을 느리게하지 그냥 트릭입니다. 당신은 .to_yaml 사용해야합니다.

    정확한 결과 :

    MyModel.where("mycode = ?", [43565, 43402].to_yaml)
    #=> [#<MyModel id:...]
    

    단지 MySQL을위한 테스트.

  3. ==============================

    3.직렬화 된 배열은 특히 패션 등의 데이터베이스에 저장됩니다 :

    직렬화 된 배열은 특히 패션 등의 데이터베이스에 저장됩니다 :

    [1, 2, 3, 4]
    in
    1\n 2\n 3\n etc
    

    따라서 쿼리가 될 것이다

    MyModel.where("mycode like ?", "% 2\n%")
    

    % 2 사이의 공간을 넣어.

  4. ==============================

    4.Noodl의 대답은 완전히 올바른 권리 만이 아니다.

    Noodl의 대답은 완전히 올바른 권리 만이 아니다.

    정말 당신이 사용중인 데이터베이스 / ORM 어댑터에 따라 달라집니다 예를 PostgreSQL을 지금 저장하고 해시 / JSON를 검색 할 수 있습니다에 대한 - hstore을 확인하십시오. 나는 PostgreSQL을위한 액티브 어댑터가 이제 제대로 처리하는 읽기 기억. 당신이 그런 식으로 mongoid 또는 무언가를 사용하는 경우 그리고 - 당신은 어디서나 데이터베이스 수준에서 (즉, JSON) 구조화되지 않은 데이터를 사용하고 있습니다.

    당신은 DB를 사용하는 경우에는 정말 해시를 처리 할 수 ​​- MySQL은 / ​​액티브 조합처럼 - 그 유일한 이유는 당신이 직렬화 필드을 사용하면 필요에 따라 일부 백그라운드 프로세스 및 디스플레이 / 출력 / 쓰기를 만들 수 SOMET 데이터입니다 - 정말 자신이 선호하는 템플릿 컬러 -I처럼 (및 사용자 옵션 - 나는 내 경험에서 찾을 수있는 유일한 두 가지 용도는 (좀 평균과 중앙값 제품에 대한 저장해야 제품 모델에 합계 필드와 같은) 일부 보고서는 )이 쿼리를 할 필요가 없습니다 - 그러나 사용자 정보를 - 메일 링리스트에 대한 구독처럼 - 이메일 폭발에 대한 검색 할 필요가있다.

    최신 정보 2017 MariaDB와 MySQL 지원 JSON 두 필드 종류를 사용합니다.

  5. ==============================

    5.좋은 소식! 당신이 (레일 4 슈퍼 쉬운) hstore와 PostgreSQL을를 사용하는 경우, 당신은 지금 완전히 직렬화 된 데이터를 검색 할 수 있습니다. 이 편리한 가이드, 여기에 PG에서 구문 문서입니다.

    좋은 소식! 당신이 (레일 4 슈퍼 쉬운) hstore와 PostgreSQL을를 사용하는 경우, 당신은 지금 완전히 직렬화 된 데이터를 검색 할 수 있습니다. 이 편리한 가이드, 여기에 PG에서 구문 문서입니다.

    내 경우에는 내가 시설이라는 hstore 열에 해시로 저장 사전을 가지고있다. 내가 해시 1의 값이 두 쿼리의 설비를 확인하려면, 그냥 할

    House.where("amenities @> 'wifi => 1' AND amenities @> 'pool => 1'")
    

    개선을위한 만세!

  6. ==============================

    6.당신은 SQL LIKE 문을 사용하여 직렬화 열을 조회 할 수 있습니다.

    당신은 SQL LIKE 문을 사용하여 직렬화 열을 조회 할 수 있습니다.

     MyModel.where("mycode LIKE '%?%'", 43402)
    

    이렇게 빨리?, 그러나, 당신은 매개 변수로 배열을 사용할 수 없습니다 등이 사용하는 것보다.

  7. ==============================

    7.MySQL의에서 직렬화 된 데이터를 사용하는 방법에 대해 설명합니다 프렌드에서 2009 년 블로그 포스트가 있습니다.

    MySQL의에서 직렬화 된 데이터를 사용하는 방법에 대해 설명합니다 프렌드에서 2009 년 블로그 포스트가 있습니다.

    당신이 할 수있는 것은 테이블을 만드는 것입니다 당신이 검색하려는 데이터에 대한 인덱스와 같은 기능.

    당신의 예에서 모델은 다음과 같이 보일 것입니다 :

    class MyModel < ApplicationRecord
      # id, name, other fields...
      serialize :mycode, Array
    end
    
    class Item < ApplicationRecord
      # id, value...
      belongs_to :my_model
    end
    

    당신이 MyModel을 저장하면 인덱스를 만들려면이 같은 작업을 수행 할 수 있습니다 :

    Item.where(my_model: self).destroy
    self.mycode.each do |mycode_item|
      Item.create(my_model: self, value: mycode_item)
    end
    

    조회 할 및 검색 할 때 그럼 그냥 할 :

    Item.where(value: [43565, 43402]).all.map(&:my_model)
    Item.where(value: 43402).all.map(&:my_model)
    

    당신은 간단을 만들기 위해 MyModel하는 방법을 추가 할 수 있습니다 :

    def find_by_mycode(value_or_values)
      Item.where(value: value_or_values).all.map(&my_model)
    end
    
    MyModel.find_by_mycode([43565, 43402])
    MyModel.find_by_mycode(43402)
    

    속도 일을하려면 해당 테이블에 대한 SQL 인덱스를 생성 할 것입니다.

  8. from https://stackoverflow.com/questions/9814622/searching-serialized-data-using-active-record by cc-by-sa and MIT license