NoSQLデータベースは、従来の1対多または1対1の関係を必要とせずに、より複雑な構造を許容することでリレーショナルデータベースと異なります。代わりに、NoSQLデータベースは、配列やサブドキュメントなどの柔軟なタイプを活用して、関連データを効率的に単一のドキュメント内に格納します。この柔軟性により、開発者はアプリケーションのクエリやパフォーマンスのニーズに適したモデルを設計できます。
Jakarta NoSQLは、MongoDBを含むNoSQLデータベースとのやり取りを簡素化するJavaフレームワークです。データがどのようにマップされ、格納されるかを決定する注釈を提供し、埋め込まれたオブジェクトがグループ化されるかフラットな方法で格納されるかを開発者が制御できます。
MongoDBとJakarta NoSQLを使用する際に、ドキュメントの構造をどのようにするかが重要です。フラット構造とグループ構造の間の選択は、データの格納、クエリ、取得方法に影響を与えます。この記事では、実践例を使用してこれら2つのアプローチを探ります。
Jakarta NoSQLとProductエンティティ
フラット構造とグループ構造を理解するために、まずProduct
エンティティを紹介し、Jakarta NoSQLの注釈がどのように機能するかを見てみましょう。
public class Product {
ObjectIdConverter.class) (
private String id;
private String name;
private Manufacturer manufacturer;
private List<String> tags;
private Set<Category> categories;
Product(String name, Manufacturer manufacturer, List<String> tags, Set<Category> categories) {
this.name = name;
this.manufacturer = manufacturer;
this.tags = tags;
this.categories = categories;
}
public static ProductBuilder builder() {
return new ProductBuilder();
}
}
さて、Jakarta NoSQLの注釈に基づいてmanufacturer
フィールドを異なる方法で格納できるかを探ってみましょう。
グループ化された構造とフラット構造の理解
グループ化された構造
グループ化された構造は、文書内の関連情報を明確なオブジェクトに整理します。このアプローチは可読性を向上させ、より清潔なドメインモデリングを実践できます。Jakarta NoSQLは、@Embeddable(Embeddable.EmbeddableType.GROUPING)
を使用することでこれを実現しています。
例:
{
"_id": { "$oid": "67b264520abd020ec0eb9a4c" },
"categories": [
{ "name": "Computers", "description": "All computers" },
{ "name": "Electronics", "description": "All electronics" }
],
"manufacturer": {
"address": "One Infinite Loop Cupertino, CA 95014",
"name": "Apple",
"contactNumber": "+1-408-996-1010"
},
"name": "MacBook Pro",
"tags": ["smartphone", "tablet", "laptop"]
}
ここでは、製造業者がグループ化され、そのプロパティがトップレベルにあるのではなく、別のサブオブジェクトに格納されます。
Embeddable.EmbeddableType.GROUPING) (
public record Manufacturer( String name, String address, String contactNumber) {}
フラット構造
関連情報を同じドキュメント内に保持し、リストやネストされたフィールドを直接埋め込むフラット構造を維持します。Jakarta NoSQLは、@Embeddable(Embeddable.EmbeddableType.FLAT)
を使用することでこれを可能にします。このアプローチは、複雑なクエリを必要とせずにすべての詳細に迅速にアクセスしたい場合に有益です。
例:
{
"_id": { "$oid": "67b22d20c921154b0223b27b" },
"address": "One Infinite Loop Cupertino, CA 95014",
"categories": [
{ "name": "Electronics", "description": "All electronics" },
{ "name": "Computers", "description": "All computers" }
],
"contactNumber": "+1-408-996-1010",
"name": "Apple",
"tags": ["smartphone", "tablet", "laptop"]
}
このアプローチは、製造業者の詳細を直接ドキュメントに格納します。
Embeddable.EmbeddableType.FLAT) (
public record Manufacturer( String name, String address, String contactNumber) {}
Jakarta NoSQLでの例の使用
次のコードスニペットは、Jakarta NoSQLがこれらの構造をどのように統合するかを示しています。
public class App {
public static void main(String[] args) {
var faker = new Faker();
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
var template = container.select(DocumentTemplate.class).get();
var electronicsCategory = new Category("Electronics", "All electronics");
var computerCategory = new Category("Computers", "All computers");
var tags = List.of("smartphone", "tablet", "laptop");
var manufacturer = new Manufacturer("Apple", "One Infinite Loop Cupertino, CA 95014", "+1-408-996-1010");
Product macBookPro = Product.builder().categories(Set.of(electronicsCategory, computerCategory))
.manufacturer(manufacturer)
.name("MacBook Pro")
.tags(tags)
.build();
Product product = template.insert(macBookPro);
System.out.println("Product saved: " + product);
}
}
}
適切なアプローチの選択
- すべてのプロパティを同じレベルで簡単に配置する必要がある場合は、フラット構造を使用します。
- 可読性と保守性を向上させるために関連データを論理的なサブオブジェクトに整理する場合は、グループ化された構造を使用します。
結論
Jakarta NoSQLでは、@Embeddable(Embeddable.EmbeddableType)
を使用してMongoDBドキュメントの構造を柔軟に設計することができます。 フラットまたはグループ化された構造を選択するかは、データアクセスパターンとモデリングの好みに依存します。これらのアプローチを理解することで、効率的なデータベース設計が可能となり、クエリをより効果的に行うことができ、同時にドメインモデルを清潔でよく構造化された状態に保つことができます。
完全なコードについては、GitHubリポジトリをご覧ください。
ビデオ
Source:
https://dzone.com/articles/handling-embedded-data-in-nosql-with-java