22 Haziran 2023 Perşembe

JSON ->> Operator - Nesnenin Alanına Erişir WHERE Cümlesinde Kullanılabilir

Giriş
Açıklaması şöyle. Bu operatör hem JSON hem de JSONB için kullanılabilir
When we use ->> operator of JSONB, PostgreSQL can use B-tree or Hash index for processing the operations. ->> operator returns the value of the specified attribute in text format. 

Kullanım
İki kullanımı var
1. Nesnenin bir alanının değerine text olarak erişebiliriz. Açıklaması şöyle
Postgres supports JSON type from v9.2. It has added many operators and functions for data manipulation of JSON. The operator -> returns JSON object field by key. The operator ->> returns JSON object field by text.
2. WHERE cümlesinde kullanılabilir

Örnek
Elimizde şöyle bir tablo olsun ve tabloya veri girelim
CREATE TABLE sensor_data (
    id SERIAL NOT NULL PRIMARY KEY,
    data JSON NOT NULL
);

INSERT INTO sensor_data (data)
  VALUES('{ "ip": "J10.3.2.4", "payload": {"temp": "33.5","brightness": "73"}}');
Veriyi sorgulamak için şöyle yaparız. Çıktı olarak ip değerlerini text olarak alırız.
SELECT data->> 'ip' AS ip FROM sensor_data;
Örnek - = Koşulu
Şöyle yaparız
SELECT orders FROM lunchorders WHERE orders ->> 'order_date' = '2020-12-11';
Örnek - >  Koşulu
Şöyle yaparız.
SELECT * FROM lunchorders WHERE  (orders -> 'order_details' ->> 'cost')::numeric > 4.50;
Örnek - LIKE
Şöyle yaparız
SELECT * FROM user_details WHERE details ->> 'alternateContacts' like '%777%';

JPA
Elimizde şöyle bir tablo olsun
CREATE TABLE employee (
  id SERIAL PRIMARY KEY,
  name VARCHAR(255),
  data JSONB
);
Entity şöyle olsun. Burada JSONB verisini Java'da String olarak saklıyoruz
@Entity
@Getter
@Setter
@Table(name = "employee")
public class Employee {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;

  @Column(columnDefinition = "jsonb")
  private String data;
}
SpringBoot projesinde @Query yani SQL ile şöyle yaparızJSON ->> Operator kullanılıyor
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

  @Query(value = "SELECT * FROM employee WHERE data->>'department' = ?1", 
         nativeQuery = true)
  List<Employee> findByDepartment(String department);
}
Specification ile şöyle yaparız. Burada hasDepartment() bir static factory ve bir tane Specification döndürülüyor. Specification Root ve CriteriaQuery nesnelerini kullanarak Type Safe Query imkanı tanıyor. Burada JSON ->> Operator yerine aynı şey olan jsonb_extract_path_text() kullanılıyor.
@Repository
public interface EmployeeSpecificationRepository extends JpaRepository<Employee, Long>, 
  JpaSpecificationExecutor<Employee> {
}

public class EmployeeSpecification {

  public static Specification<Employee> hasDepartment(String department) {
    return new Specification<Employee>() {
      @Override
      public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query,
        CriteriaBuilder cb) {
        return cb.equal(
          cb.function("jsonb_extract_path_text", String.class, root.get("data"), 
            cb.literal("department")),
          department
        );
      }
    };
  }
}
Her iki yöntemi de kullanan Controller için şöyle yaparız
@RestController
public class EmployeeController {

  @Autowired
  private EmployeeRepository employeeRepository;

  @Autowired
  private EmployeeSpecificationRepository employeeSpecificationRepository;

  @GetMapping("/employees/{department}")
  public List<Employee> getByDepartment(@PathVariable String department) {
    return employeeRepository.findByDepartment(department);
  }

  @GetMapping("/employees/Specification/{department}")
  public List<Employee> getBySpecificationDepartment(@PathVariable String department) {
    Specification<Employee> spec = EmployeeSpecification.hasDepartment(department);
    return employeeSpecificationRepository.findAll(spec);
  }
}










Hiç yorum yok:

Yorum Gönder