Docs Menu
Docs Home
/
Relational Migrator
/ /

Oracleパッケージの変換

項目一覧

  • このタスクについて
  • 始める前に
  • 手順

クエリ 変換を使用して、 OracleパッケージをMongoDBコードにインポートして変換できます。クエリ ドライバーは、 SQLコードを変換する際にプロジェクトに定義されたマッピング ルールとスキーマ変換を考慮します。

  • クエリ ドライバーはAIテクノロジーを使用しますが、長いクエリや複雑なクエリ、トリガー、パッケージ、または保存された手順を変換できない場合があります。正しく変換されないクエリもあれば、まったく変換されないクエリもあります。詳しくは、「 AIとデータ使用状況の情報 」を参照してください。

  • クエリ ドライバーは、リレーショナル スキーマ、MongoDB スキーマ、現在のプロジェクト内のマッピング ルールを使用して、クエリを変換する方法を決定します。 クエリがリレーショナル スキーマにないテーブルを参照する場合、または MongoDB コレクションにマップされていない場合、変換が失敗したり不正確になることがあります。

  • 変換されたクエリ、trigger、ビュー、パッケージ、保存された手順はプロジェクトに保存され、プロジェクトのインポートおよびエクスポート後も保持されます。

  • SQLクエリは40 、 000テキスト文字に制限されています。

  • 左側の [ Query Converterペインで以前の変換履歴を表示できます。 各変換には、変換の結果を示す アイコンがあります。 オブジェクトの横に アイコンがない場合、変換はまだ試行されていません。

    Icon
    説明

    スピナー

    変換が実行中です。

    緑色のチェックマーク

    変換は成功しました。

    赤色の句読点

    前回の試行では変換は失敗しました。

  • MongoDBには、 Oracleパッケージ向けの公式シノニムオブジェクトタイプはありません。代わりに、 MongoDBはデータベースロジックをホストするカスタムJavaScriptとドライバー コードをサポートしています。アプリケーションをMongoDBに移行する場合は、アプリケーションのニーズに最も適したプログラミング言語とホスティング オプションを選択する必要があります。変換されたOracleパッケージコードは、アプリケーション内または Atlas Function を使用してホストできます。

  • クエリ 変換によって生成されたコードは、本番環境に配置する前に、必ず確認とテストを行ってください。

1

[ Code Generationタブから、 Query Converterペインをクリックします。

2
  • 左側のペインで [0}] ボタンをクリックします。+ Add

  • [Import From Database] をクリックします。

3

ソース データベースにまだ接続していない場合は、ソースデータベースへの接続の詳細を指定し、 Connect をクリックしデータベース。

Relational Migratorのデータベース接続の詳細については、「 データベース接続 」を参照してください。

4
  1. Import from databaseモーダルで、次をクリックします: Databaseの横にあるアイコン。

  2. をクリックしますスキーマの横にある アイコン。

  3. をクリックしますPackagesの横にあるアイコン。

    Tip

    Oracleパッケージを変換するためには、パッケージ名の横にある アイコンをクリックします。

  4. [Save] をクリックします。

    データベーススキーマ内の各パッケージのコードはプロジェクトにインポートされ、Packages の下の Query Converter ペインに表示されます。

5
  1. 左側のペインから Packages の下のパッケージ名をクリックします。

    コードはImported Packageペインに表示されます。

  2. ドロップダウンからTarget Languageを選択します。

    クエリ 変換は、Javascript、 C#、およびJavaへのOracleパッケージ変換をサポートしています。

    注意

    Javaを使用している場合は、 Return a domain object where possible を選択することもできます。選択すると、クエリが単一のMongoDBコレクションでのみ動作する場合、クエリ 変換には POJO クラスに基づいて厳密に型指定されたJavaエンティティが含まれます。

  3. [ Convert ] ボタンをクリックします。 クエリ ドライバーがコードを変換するまで待ちます。

    変換された MongoDB コードはConverted MongoDB Queryペインに表示されます。

    クエリ 変換にエラーが発生した場合は、 Converted MongoDB Queryペインで詳細を表示できます。

  4. をクリックしますConverted MongoDB Queryペインの [] アイコンを使用して、MongoDB コードをクリップボードにコピーします。

  5. 生成された MongoDB コードをテストして検証します。

    Tip

    Filter テキスト ボックスを使用して、オブジェクト名 とSQL構文に基づいて、クエリ、保存済み手順、trigger、パッケージ、ビューをフィルタリングできます。

クエリ 変換は、パッケージを Javascript、 C#、またはJavaコードに変換できます。以下の例では、各言語への変換を示しています。

CREATE OR REPLACE EDITIONABLE PACKAGE "TICKETMANAGEMENT" IS
procedure sellTickets(person_id IN NUMBER, event_id IN NUMBER, quantity IN NUMBER DEFAULT 1);
procedure generateTicketActivity(transaction_delay NUMBER, max_transactions IN NUMBER DEFAULT 1000);
procedure generateTransferActivity(transaction_delay IN NUMBER DEFAULT 5, max_transactions IN NUMBER DEFAULT 100);
end ticketManagement;
/
CREATE OR REPLACE EDITIONABLE PACKAGE BODY "TICKETMANAGEMENT" AS
-- forward type declaration
TYPE eventTab IS TABLE OF sporting_event%ROWTYPE INDEX BY BINARY_INTEGER;
TYPE eventRecType IS RECORD ( sport_name sport_type.name%TYPE,
home_team_name sport_team.name%TYPE,
away_team_name sport_team.name%TYPE,
home_field sport_location.name%TYPE,
date_time sporting_event.start_date_time%TYPE);
-- package variables
g_max_person_id person.id%TYPE;
g_min_person_id person.id%TYPE;
-- forward declarations
function get_open_events return eventTab;
function get_event_details(event_id IN NUMBER) RETURN eventRecType;
procedure sellRandomTickets;
--------------------------------
-- sell tickets proc
--------------------------------
procedure sellTickets(person_id IN NUMBER, event_id IN NUMBER, quantity IN NUMBER DEFAULT 1) IS
not_enough_seats EXCEPTION;
p_person_id person.id%TYPE := person_id;
p_event_id sporting_event.id%TYPE := event_id;
p_quantity NUMBER := quantity;
r_seat_level sporting_event_ticket.seat_level%TYPE;
r_seat_section sporting_event_ticket.seat_section%type;
r_seat_row sporting_event_ticket.seat_row%type;
event_rec eventRecType;
CURSOR adjacent_seats(p_seat_level NUMBER, p_seat_section VARCHAR2, p_seat_row VARCHAR2) IS
SELECT * FROM sporting_event_ticket
WHERE sporting_event_id = p_event_id
AND seat_level = p_seat_level
AND seat_section = p_seat_section
AND seat_row = p_seat_row
ORDER BY seat_level, seat_section, seat_row
FOR UPDATE OF ticketholder_id;
cur_ticket sporting_event_ticket%ROWTYPE;
BEGIN
event_rec := get_event_details(p_event_id);
BEGIN
SELECT seat_level, seat_section, seat_row
INTO r_seat_level, r_seat_section, r_seat_row
FROM (SELECT seat_level,seat_section,seat_row
FROM sporting_event_ticket
WHERE sporting_event_id = p_event_id
AND ticketholder_id IS NULL
GROUP BY seat_level,seat_section,seat_row
HAVING COUNT(*) >= p_quantity)
WHERE rownum < 2;
EXCEPTION WHEN NO_DATA_FOUND THEN
RAISE not_enough_seats;
END;
OPEN adjacent_seats(r_seat_level,r_seat_section,r_seat_row);
FOR i IN 1..p_quantity LOOP
FETCH adjacent_seats INTO cur_ticket;
UPDATE sporting_event_ticket
SET ticketholder_id = p_person_id
WHERE CURRENT OF adjacent_seats;
INSERT INTO ticket_purchase_hist(sporting_event_ticket_id, purchased_by_id, transaction_date_time, purchase_price)
VALUES(cur_ticket.id, p_person_id, SYSDATE, cur_ticket.ticket_price);
END LOOP;
COMMIT;
EXCEPTION WHEN not_enough_seats THEN
DBMS_OUTPUT.PUT_LINE('Sorry, there aren''t ' || p_quantity || ' adjacent seats for event:');
DBMS_OUTPUT.PUT_LINE(' ' || event_rec.home_team_name || ' VS ' || event_rec.away_team_name || ' (' || event_rec.sport_name || ')' );
DBMS_OUTPUT.PUT_LINE(' ' || event_rec.home_field || ': ' || TO_CHAR(event_rec.date_time,'DD-MON-YYYY HH:MI'));
END;
--------------------------------
-- transfer ticket
--------------------------------
procedure transferTicket(ticket_id IN NUMBER, new_ticketholder_id IN NUMBER, transfer_all IN BOOLEAN DEFAULT FALSE, price IN NUMBER DEFAULT NULL) IS
p_ticket_id NUMBER := ticket_id;
p_new_ticketholder_id NUMBER := new_ticketholder_id;
p_price NUMBER := price;
xferall NUMBER := 0;
old_ticketholder_id NUMBER;
last_txn_date DATE;
CURSOR txfr_cur(p_purchased_by NUMBER, p_txn_date_time DATE) IS
SELECT * FROM ticket_purchase_hist
WHERE purchased_by_id = p_purchased_by
AND transaction_date_time = p_txn_date_time;
BEGIN
IF transfer_all THEN
xferall := 1;
END IF;
SELECT max(h.transaction_date_time) as transaction_date_time
,t.ticketholder_id as ticketholder_id
INTO last_txn_date, old_ticketholder_id
FROM ticket_purchase_hist h
,sporting_event_ticket t
WHERE t.id = p_ticket_id
AND h.purchased_by_id = t.ticketholder_id
AND ((h.sporting_event_ticket_id = p_ticket_id) OR (xferall = 1) )
GROUP BY t.ticketholder_id;
FOR xrec IN txfr_cur(old_ticketholder_id, last_txn_date) LOOP
UPDATE sporting_event_ticket
SET ticketholder_id = p_new_ticketholder_id
WHERE id = xrec.sporting_event_ticket_id;
INSERT INTO ticket_purchase_hist(sporting_event_ticket_id, purchased_by_id, transferred_from_id, transaction_date_time, purchase_price)
VALUES(xrec.sporting_event_ticket_id, p_new_ticketholder_id, old_ticketholder_id, SYSDATE, NVL(p_price,xrec.purchase_price));
END LOOP;
COMMIT; -- commit the group
EXCEPTION WHEN OTHERS THEN
ROLLBACK;
END;
---------------------------------------
-- generate ticket purchase activity
---------------------------------------
PROCEDURE generateTicketActivity(transaction_delay NUMBER, max_transactions IN NUMBER DEFAULT 1000) IS
txn_count NUMBER := 0;
BEGIN
WHILE txn_count < max_transactions LOOP
sellRandomTickets;
txn_count := txn_count +1;
dbms_lock.sleep(transaction_delay);
END LOOP;
END;
---------------------------------------
-- generate ticket purchase activity
---------------------------------------
PROCEDURE generateTransferActivity(transaction_delay IN NUMBER DEFAULT 5, max_transactions IN NUMBER DEFAULT 100) IS
txn_count NUMBER := 0;
min_tik_id sporting_event_ticket.id%TYPE;
max_tik_id sporting_event_ticket.id%TYPE;
tik_id sporting_event_ticket.id%TYPE;
new_ticketholder person.id%TYPE;
xfer_all BOOLEAN;
chg_price BOOLEAN;
new_price sporting_event_ticket.ticket_price%TYPE;
BEGIN
WHILE txn_count < max_transactions LOOP
SELECT min(sporting_event_ticket_id), max(sporting_event_ticket_id)
INTO min_tik_id, max_tik_id
FROM ticket_purchase_hist;
SELECT MAX(sporting_event_ticket_id)
INTO tik_id
FROM ticket_purchase_hist
WHERE sporting_event_ticket_id <= dbms_random.value(min_tik_id,max_tik_id);
new_ticketholder := TRUNC(dbms_random.value(g_min_person_id,g_max_person_id));
xfer_all := (ROUND(dbms_random.value(1,5)) < 5); -- transfer all tickets 80% of the time
new_price := NULL;
chg_price := (ROUND(dbms_random.value(1,3)) = 1); -- 30% of the time change price
IF chg_price THEN
SELECT dbms_random.value(0.8,1.2) * ticket_price INTO new_price
FROM sporting_event_ticket
WHERE id = tik_id;
END IF;
transferTicket(tik_id, new_ticketholder, xfer_all, new_price);
txn_count := txn_count +1;
dbms_lock.sleep(transaction_delay);
END LOOP;
EXCEPTION WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No tickets available to transfer.');
END;
--------------------------------
-- get event details
--------------------------------
function get_event_details(event_id IN NUMBER) RETURN eventRecType IS
eventRec eventRecType;
p_event_id sporting_event.id%TYPE := event_id;
BEGIN
SELECT e.sport_type_name
,h.name
,a.name
,l.name
,e.start_date_time
INTO eventRec.sport_name, eventRec.home_team_name, eventRec.away_team_name, eventRec.home_field, eventRec.date_time
FROM sporting_event e
,sport_team h
,sport_team a
,sport_location l
WHERE e.id = p_event_id
AND e.home_team_id = h.id
AND e.away_team_id = a.id
AND e.location_id = l.id;
RETURN eventRec;
END;
--------------------------------
-- sell random tickets proc
--------------------------------
procedure sellRandomTickets IS
event_tab eventTab;
ticket_holder person.id%TYPE;
row_ct NUMBER(8);
event_idx NUMBER(8);
event_id NUMBER;
quantity NUMBER;
BEGIN
event_tab := get_open_events;
row_ct := event_tab.COUNT;
event_idx := TRUNC(dbms_random.value(1,row_ct));
event_id := event_tab(event_idx).id;
ticket_holder := TRUNC(dbms_random.value(g_min_person_id,g_max_person_id));
quantity := dbms_random.value(1,6);
sellTickets(ticket_holder,event_id,quantity);
END;
---------------------------------------
-- get open events function
---------------------------------------
function get_open_events return eventTab IS
event_tab eventTab;
CURSOR open_events IS
SELECT *
FROM sporting_event
WHERE sold_out = 0
ORDER BY start_date_time;
row_num BINARY_INTEGER := 1;
BEGIN
FOR oe_rec IN open_events LOOP
event_tab(row_num) := oe_rec;
row_num := row_num +1;
END LOOP;
return event_tab;
END;
BEGIN
--- initialize
select min(id),max(id) INTO g_min_person_id,g_max_person_id from person;
END ticketManagement;
/
class TicketManagement {
constructor(db) {
this.db = db;
this.g_max_person_id = null;
this.g_min_person_id = null;
}
async sellTickets(person_id, event_id, quantity = 1) {
const notEnoughSeats = new Error('not_enough_seats');
const p_person_id = person_id;
const p_event_id = event_id;
const p_quantity = quantity;
let r_seat_level, r_seat_section, r_seat_row;
let event_rec;
try {
event_rec = await this.get_event_details(p_event_id);
const seatData = await this.db.collection('sportingEventTicket').aggregate([
{ $match: { sportingEventId: p_event_id, ticketholderId: null } },
{ $group: { _id: { seatLevel: "$seatLevel", seatSection: "$seatSection", seatRow: "$seatRow" }, count: { $sum: 1 } } },
{ $match: { count: { $gte: p_quantity } } },
{ $limit: 1 },
{ $project: { _id: 0, seatLevel: "$_id.seatLevel", seatSection: "$_id.seatSection", seatRow: "$_id.seatRow" } }
]).toArray();
if (seatData.length === 0) throw notEnoughSeats;
r_seat_level = seatData[0].seatLevel;
r_seat_section = seatData[0].seatSection;
r_seat_row = seatData[0].seatRow;
const adjacentSeatsCursor = this.db.collection('sportingEventTicket').find({
sportingEventId: p_event_id,
seatLevel: r_seat_level,
seatSection: r_seat_section,
seatRow: r_seat_row
}).sort({ seatLevel: 1, seatSection: 1, seatRow: 1 });
for (let i = 0; i < p_quantity; i++) {
const cur_ticket = await adjacentSeatsCursor.next();
if (!cur_ticket) throw notEnoughSeats;
await this.db.collection('sportingEventTicket').updateOne(
{ _id: cur_ticket._id },
{ $set: { ticketholderId: p_person_id } }
);
await this.db.collection('ticketPurchaseHist').insertOne({
sportingEventTicketId: cur_ticket.id,
purchasedById: p_person_id,
transactionDateTime: new Date(),
purchasePrice: cur_ticket.ticketPrice
});
}
} catch (err) {
if (err === notEnoughSeats) {
console.log(`Sorry, there aren't ${p_quantity} adjacent seats for event:`);
console.log(` ${event_rec.home_team_name} VS ${event_rec.away_team_name} (${event_rec.sport_name})`);
console.log(` ${event_rec.home_field}: ${event_rec.date_time.toLocaleString('en-GB', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' })}`);
} else {
throw err;
}
}
}
async $transferTicket(ticket_id, new_ticketholder_id, transfer_all = false, price = null) {
const p_ticket_id = ticket_id;
const p_new_ticketholder_id = new_ticketholder_id;
const p_price = price;
const xferall = transfer_all ? 1 : 0;
try {
const ticket = await this.db.collection('sportingEventTicket').findOne({ id: p_ticket_id });
if (!ticket) throw new Error('Ticket not found');
const lastTransaction = await this.db.collection('ticketPurchaseHist').aggregate([
{ $match: { purchased_by_id: ticket.ticketholderId, $or: [{ sporting_event_ticket_id: p_ticket_id }, { xferall: 1 }] } },
{ $group: { _id: '$ticketholderId', last_txn_date: { $max: '$transaction_date_time' } } }
]).toArray();
if (lastTransaction.length === 0) throw new Error('No transaction found');
const old_ticketholder_id = ticket.ticketholderId;
const last_txn_date = lastTransaction[0].last_txn_date;
const transactions = await this.db.collection('ticketPurchaseHist').find({
purchased_by_id: old_ticketholder_id,
transaction_date_time: last_txn_date
}).toArray();
for (const xrec of transactions) {
await this.db.collection('sportingEventTicket').updateOne(
{ id: xrec.sporting_event_ticket_id },
{ $set: { ticketholderId: p_new_ticketholder_id } }
);
await this.db.collection('ticketPurchaseHist').insertOne({
sporting_event_ticket_id: xrec.sporting_event_ticket_id,
purchased_by_id: p_new_ticketholder_id,
transferred_from_id: old_ticketholder_id,
transaction_date_time: new Date(),
purchase_price: p_price !== null ? p_price : xrec.purchase_price
});
}
} catch (error) {
console.error(error);
throw error;
}
}
async generateTicketActivity(transaction_delay, max_transactions = 1000) {
let txn_count = 0;
while (txn_count < max_transactions) {
await this.sellRandomTickets();
txn_count += 1;
await new Promise(resolve => setTimeout(resolve, transaction_delay * 1000));
}
}
async generateTransferActivity(transaction_delay = 5, max_transactions = 100) {
let txn_count = 0;
let min_tik_id, max_tik_id, tik_id, new_ticketholder, xfer_all, chg_price, new_price;
while (txn_count < max_transactions) {
const minMaxResult = await this.db.collection('ticketPurchaseHist').aggregate([
{
$group: {
_id: null,
min_tik_id: { $min: "$sportingEventTicketId" },
max_tik_id: { $max: "$sportingEventTicketId" }
}
}
]).toArray();
if (minMaxResult.length === 0) {
console.log('No tickets available to transfer.');
return;
}
min_tik_id = minMaxResult[0].min_tik_id;
max_tik_id = minMaxResult[0].max_tik_id;
const tikResult = await this.db.collection('ticketPurchaseHist').aggregate([
{
$match: {
sportingEventTicketId: { $lte: Math.random() * (max_tik_id - min_tik_id) + min_tik_id }
}
},
{
$group: {
_id: null,
tik_id: { $max: "$sportingEventTicketId" }
}
}
]).toArray();
if (tikResult.length === 0) {
console.log('No tickets available to transfer.');
return;
}
tik_id = tikResult[0].tik_id;
new_ticketholder = Math.floor(Math.random() * (this.g_max_person_id - this.g_min_person_id) + this.g_min_person_id);
xfer_all = Math.round(Math.random() * 4) < 4;
new_price = null;
chg_price = Math.round(Math.random() * 2) === 0;
if (chg_price) {
const priceResult = await this.db.collection('sportingEventTicket').findOne({ id: tik_id });
new_price = Math.random() * (1.2 - 0.8) + 0.8 * priceResult.ticketPrice;
}
await this.transferTicket(tik_id, new_ticketholder, xfer_all, new_price);
txn_count++;
await new Promise(resolve => setTimeout(resolve, transaction_delay * 1000));
}
}
async $get_event_details(event_id) {
const p_event_id = event_id;
const result = await this.db.collection('sportingEvent').aggregate([
{
$match: { id: p_event_id }
},
{
$lookup: {
from: 'sportTeam',
localField: 'homeTeamId',
foreignField: 'id',
as: 'home_team'
}
},
{
$lookup: {
from: 'sportTeam',
localField: 'awayTeamId',
foreignField: 'id',
as: 'away_team'
}
},
{
$lookup: {
from: 'sportLocation',
localField: 'locationId',
foreignField: 'id',
as: 'location'
}
},
{
$unwind: '$home_team'
},
{
$unwind: '$away_team'
},
{
$unwind: '$location'
},
{
$project: {
sport_name: '$sportTypeName',
home_team_name: '$home_team.name',
away_team_name: '$away_team.name',
home_field: '$location.name',
date_time: '$startDateTime'
}
}
]).toArray();
if (result.length === 0) {
throw new Error('Event not found');
}
return result[0];
}
async sellRandomTickets() {
const eventTab = await this.get_open_events();
const row_ct = eventTab.length;
const event_idx = Math.floor(Math.random() * row_ct);
const event_id = eventTab[event_idx].id;
const ticket_holder = Math.floor(Math.random() * (this.g_max_person_id - this.g_min_person_id + 1)) + this.g_min_person_id;
const quantity = Math.floor(Math.random() * 6) + 1;
await this.sellTickets(ticket_holder, event_id, quantity);
}
async get_open_events() {
const openEvents = await this.db.collection('sportingEvent').find({ soldOut: 0 }).sort({ startDateTime: 1 }).toArray();
return openEvents;
}
}
using MongoDB.Bson;
using MongoDB.Driver;
using System;
public class TicketManagement
{
private readonly IMongoDatabase db;
public TicketManagement(IMongoDatabase database)
{
db = database;
Initialize();
}
private decimal g_max_person_id;
private decimal g_min_person_id;
private void Initialize()
{
var personCollection = db.GetCollection<BsonDocument>("person");
var result = personCollection.Aggregate()
.Group(new BsonDocument
{
{ "_id", BsonNull.Value },
{ "minId", new BsonDocument("$min", "$id") },
{ "maxId", new BsonDocument("$max", "$id") }
})
.FirstOrDefault();
g_min_person_id = result["minId"].AsDecimal;
g_max_person_id = result["maxId"].AsDecimal;
}
public void sellTickets(decimal person_id, decimal event_id, int quantity = 1)
{
var notEnoughSeats = new Exception("Not enough seats");
var p_person_id = person_id;
var p_event_id = event_id;
var p_quantity = quantity;
int r_seat_level;
string r_seat_section;
string r_seat_row;
var event_rec = get_event_details(p_event_id);
try
{
var seatQuery = db.GetCollection<BsonDocument>("sportingEventTicket")
.Aggregate()
.Match(new BsonDocument { { "sportingEventId", p_event_id }, { "ticketholderId", BsonNull.Value } })
.Group(new BsonDocument { { "_id", new BsonDocument { { "seatLevel", "$seatLevel" }, { "seatSection", "$seatSection" }, { "seatRow", "$seatRow" } } }, { "count", new BsonDocument("$sum", 1) } })
.Match(new BsonDocument("count", new BsonDocument("$gte", p_quantity)))
.Limit(1)
.Project(new BsonDocument { { "seatLevel", "$_id.seatLevel" }, { "seatSection", "$_id.seatSection" }, { "seatRow", "$_id.seatRow" } })
.FirstOrDefault();
if (seatQuery == null)
{
throw notEnoughSeats;
}
r_seat_level = seatQuery["seatLevel"].AsInt32;
r_seat_section = seatQuery["seatSection"].AsString;
r_seat_row = seatQuery["seatRow"].AsString;
}
catch
{
throw notEnoughSeats;
}
var adjacentSeatsCursor = db.GetCollection<BsonDocument>("sportingEventTicket")
.Find(new BsonDocument { { "sportingEventId", p_event_id }, { "seatLevel", r_seat_level }, { "seatSection", r_seat_section }, { "seatRow", r_seat_row } })
.Sort(new BsonDocument { { "seatLevel", 1 }, { "seatSection", 1 }, { "seatRow", 1 } })
.ToCursor();
using (var session = db.Client.StartSession())
{
session.StartTransaction();
try
{
for (int i = 0; i < p_quantity; i++)
{
if (!adjacentSeatsCursor.MoveNext())
{
throw notEnoughSeats;
}
var cur_ticket = adjacentSeatsCursor.Current;
var updateFilter = Builders<BsonDocument>.Filter.Eq("_id", cur_ticket["_id"]);
var update = Builders<BsonDocument>.Update.Set("ticketholderId", p_person_id);
db.GetCollection<BsonDocument>("sportingEventTicket").UpdateOne(updateFilter, update);
var purchaseHistDoc = new BsonDocument
{
{ "sportingEventTicketId", cur_ticket["id"] },
{ "purchasedById", p_person_id },
{ "transactionDateTime", DateTime.Now },
{ "purchasePrice", cur_ticket["ticketPrice"] }
};
db.GetCollection<BsonDocument>("ticketPurchaseHist").InsertOne(purchaseHistDoc);
}
session.CommitTransaction();
}
catch
{
session.AbortTransaction();
throw;
}
}
}
public void generateTicketActivity(decimal transaction_delay, int max_transactions = 1000)
{
int txn_count = 0;
while (txn_count < max_transactions)
{
sellRandomTickets();
txn_count += 1;
System.Threading.Thread.Sleep((int)(transaction_delay * 1000));
}
}
public void generateTransferActivity(int transaction_delay = 5, int max_transactions = 100)
{
int txn_count = 0;
decimal min_tik_id, max_tik_id, tik_id;
decimal new_ticketholder;
bool xfer_all;
bool chg_price;
decimal? new_price;
while (txn_count < max_transactions)
{
var minMaxResult = db.GetCollection<BsonDocument>("ticketPurchaseHist")
.Aggregate()
.Group(new BsonDocument
{
{ "_id", BsonNull.Value },
{ "min_tik_id", new BsonDocument("$min", "$sporting_event_ticket_id") },
{ "max_tik_id", new BsonDocument("$max", "$sporting_event_ticket_id") }
})
.FirstOrDefault();
if (minMaxResult == null)
{
Console.WriteLine("No tickets available to transfer.");
return;
}
min_tik_id = minMaxResult["min_tik_id"].AsDecimal;
max_tik_id = minMaxResult["max_tik_id"].AsDecimal;
var tikResult = db.GetCollection<BsonDocument>("ticketPurchaseHist")
.Find(Builders<BsonDocument>.Filter.Lte("sporting_event_ticket_id", new BsonDecimal128(new Random().NextDouble() * (double)(max_tik_id - min_tik_id) + (double)min_tik_id)))
.Sort(Builders<BsonDocument>.Sort.Descending("sporting_event_ticket_id"))
.FirstOrDefault();
if (tikResult == null)
{
Console.WriteLine("No tickets available to transfer.");
return;
}
tik_id = tikResult["sporting_event_ticket_id"].AsDecimal;
new_ticketholder = (decimal)(new Random().NextDouble() * (double)(g_max_person_id - g_min_person_id) + (double)g_min_person_id);
xfer_all = new Random().Next(1, 6) < 5;
new_price = null;
chg_price = new Random().Next(1, 4) == 1;
if (chg_price)
{
var ticketResult = db.GetCollection<BsonDocument>("sportingEventTicket")
.Find(Builders<BsonDocument>.Filter.Eq("id", tik_id))
.FirstOrDefault();
if (ticketResult != null)
{
new_price = ticketResult["ticket_price"].AsDecimal * (decimal)(new Random().NextDouble() * 0.4 + 0.8);
}
}
transferTicket(tik_id, new_ticketholder, xfer_all, new_price);
txn_count++;
System.Threading.Thread.Sleep(transaction_delay * 1000);
}
}
public List<BsonDocument> get_open_events()
{
var event_tab = new List<BsonDocument>();
var open_events = db.GetCollection<BsonDocument>("sportingEvent")
.Find(Builders<BsonDocument>.Filter.Eq("soldOut", 0))
.Sort(Builders<BsonDocument>.Sort.Ascending("startDateTime"))
.ToList();
foreach (var oe_rec in open_events)
{
event_tab.Add(oe_rec);
}
return event_tab;
}
public eventRecType get_event_details(decimal event_id)
{
var eventRec = new eventRecType();
var p_event_id = event_id;
var pipeline = new[]
{
new BsonDocument("$match", new BsonDocument("id", p_event_id)),
new BsonDocument("$lookup", new BsonDocument
{
{ "from", "sportTeam" },
{ "localField", "homeTeamId" },
{ "foreignField", "id" },
{ "as", "homeTeam" }
}),
new BsonDocument("$lookup", new BsonDocument
{
{ "from", "sportTeam" },
{ "localField", "awayTeamId" },
{ "foreignField", "id" },
{ "as", "awayTeam" }
}),
new BsonDocument("$lookup", new BsonDocument
{
{ "from", "sportLocation" },
{ "localField", "locationId" },
{ "foreignField", "id" },
{ "as", "location" }
}),
new BsonDocument("$unwind", "$homeTeam"),
new BsonDocument("$unwind", "$awayTeam"),
new BsonDocument("$unwind", "$location"),
new BsonDocument("$project", new BsonDocument
{
{ "sport_name", "$sportTypeName" },
{ "home_team_name", "$homeTeam.name" },
{ "away_team_name", "$awayTeam.name" },
{ "home_field", "$location.name" },
{ "date_time", "$startDateTime" }
})
};
var result = db.GetCollection<BsonDocument>("sportingEvent").Aggregate<BsonDocument>(pipeline).FirstOrDefault();
if (result != null)
{
eventRec.sport_name = result["sport_name"].AsString;
eventRec.home_team_name = result["home_team_name"].AsString;
eventRec.away_team_name = result["away_team_name"].AsString;
eventRec.home_field = result["home_field"].AsString;
eventRec.date_time = result["date_time"].ToUniversalTime();
}
return eventRec;
}
void sellRandomTickets()
{
var eventTab = getOpenEvents();
var rowCt = eventTab.Count;
var eventIdx = (int)Math.Truncate(new Random().NextDouble() * (rowCt - 1)) + 1;
var eventId = eventTab[eventIdx].id;
var ticketHolder = (int)Math.Truncate(new Random().NextDouble() * (g_max_person_id - g_min_person_id) + g_min_person_id);
var quantity = (int)Math.Truncate(new Random().NextDouble() * 5) + 1;
sellTickets(ticketHolder, eventId, quantity);
}
void transferTicket(decimal ticket_id, decimal new_ticketholder_id, bool transfer_all = false, decimal? price = null)
{
var p_ticket_id = ticket_id;
var p_new_ticketholder_id = new_ticketholder_id;
var p_price = price;
var xferall = transfer_all ? 1 : 0;
decimal old_ticketholder_id;
DateTime last_txn_date;
var txfr_cur = db.GetCollection<BsonDocument>("ticketPurchaseHist")
.Find(Builders<BsonDocument>.Filter.And(
Builders<BsonDocument>.Filter.Eq("purchased_by_id", old_ticketholder_id),
Builders<BsonDocument>.Filter.Eq("transaction_date_time", last_txn_date)
)).ToList();
var result = db.GetCollection<BsonDocument>("ticketPurchaseHist").Aggregate()
.Match(Builders<BsonDocument>.Filter.And(
Builders<BsonDocument>.Filter.Eq("sporting_event_ticket_id", p_ticket_id),
Builders<BsonDocument>.Filter.Eq("purchased_by_id", old_ticketholder_id),
Builders<BsonDocument>.Filter.Or(
Builders<BsonDocument>.Filter.Eq("sporting_event_ticket_id", p_ticket_id),
Builders<BsonDocument>.Filter.Eq("xferall", 1)
)
))
.Group(new BsonDocument
{
{ "_id", "$ticketholder_id" },
{ "transaction_date_time", new BsonDocument("$max", "$transaction_date_time") }
})
.FirstOrDefault();
if (result != null)
{
last_txn_date = result["transaction_date_time"].ToUniversalTime();
old_ticketholder_id = result["_id"].AsDecimal;
foreach (var xrec in txfr_cur)
{
db.GetCollection<BsonDocument>("sportingEventTicket").UpdateOne(
Builders<BsonDocument>.Filter.Eq("id", xrec["sporting_event_ticket_id"]),
Builders<BsonDocument>.Update.Set("ticketholder_id", p_new_ticketholder_id)
);
db.GetCollection<BsonDocument>("ticketPurchaseHist").InsertOne(new BsonDocument
{
{ "sporting_event_ticket_id", xrec["sporting_event_ticket_id"] },
{ "purchased_by_id", p_new_ticketholder_id },
{ "transferred_from_id", old_ticketholder_id },
{ "transaction_date_time", DateTime.UtcNow },
{ "purchase_price", p_price ?? xrec["purchase_price"].AsDecimal }
});
}
}
else
{
throw new Exception("No tickets available to transfer.");
}
}
}
public class TicketManagement {
private MongoDatabase db;
private Decimal128 g_max_person_id;
private Decimal128 g_min_person_id;
public TicketManagement(MongoDatabase db) {
this.db = db;
initialize();
}
private void initialize() {
MongoCollection<Document> personCollection = db.getCollection("person");
Document minMaxPersonId = personCollection.aggregate(Arrays.asList(
Aggregates.group(null, Accumulators.min("minId", "$id"), Accumulators.max("maxId", "$id"))
)).first();
if (minMaxPersonId != null) {
g_min_person_id = minMaxPersonId.get("minId", Decimal128.class);
g_max_person_id = minMaxPersonId.get("maxId", Decimal128.class);
}
}
public void sellTickets(Number person_id, Number event_id, Number quantity) {
try {
Document eventRec = get_event_details(event_id);
Document seatInfo = db.getCollection("sportingEventTicket")
.aggregate(Arrays.asList(
Aggregates.match(Filters.and(
Filters.eq("sportingEventId", event_id),
Filters.eq("ticketholderId", null)
)),
Aggregates.group(new Document("seatLevel", "$seatLevel")
.append("seatSection", "$seatSection")
.append("seatRow", "$seatRow"),
Accumulators.sum("count", 1)
),
Aggregates.match(Filters.gte("count", quantity)),
Aggregates.limit(1)
)).first();
if (seatInfo == null) {
throw new Exception("not_enough_seats");
}
Number r_seat_level = seatInfo.getInteger("_id.seatLevel");
String r_seat_section = seatInfo.getString("_id.seatSection");
String r_seat_row = seatInfo.getString("_id.seatRow");
MongoCursor<Document> cursor = db.getCollection("sportingEventTicket")
.find(Filters.and(
Filters.eq("sportingEventId", event_id),
Filters.eq("seatLevel", r_seat_level),
Filters.eq("seatSection", r_seat_section),
Filters.eq("seatRow", r_seat_row)
))
.sort(Sorts.ascending("seatLevel", "seatSection", "seatRow"))
.iterator();
for (int i = 0; i < quantity; i++) {
if (!cursor.hasNext()) {
throw new Exception("not_enough_seats");
}
Document cur_ticket = cursor.next();
db.getCollection("sportingEventTicket").updateOne(
Filters.eq("_id", cur_ticket.getObjectId("_id")),
Updates.set("ticketholderId", person_id)
);
db.getCollection("ticketPurchaseHist").insertOne(new Document()
.append("sportingEventTicketId", cur_ticket.getDecimal("id"))
.append("purchasedById", person_id)
.append("transactionDateTime", new Date())
.append("purchasePrice", cur_ticket.getDecimal("ticketPrice"))
);
}
} catch (Exception e) {
if (e.getMessage().equals("not_enough_seats")) {
System.out.println("Sorry, there aren't " + quantity + " adjacent seats for event:");
System.out.println(" " + eventRec.getString("home_team_name") + " VS " + eventRec.getString("away_team_name") + " (" + eventRec.getString("sport_name") + ")");
System.out.println(" " + eventRec.getString("home_field") + ": " + new SimpleDateFormat("dd-MMM-yyyy HH:mm").format(eventRec.getDate("date_time")));
} else {
e.printStackTrace();
}
}
}
public void generateTicketActivity(int transaction_delay, int max_transactions) {
int txn_count = 0;
while (txn_count < max_transactions) {
sellRandomTickets();
txn_count++;
try {
Thread.sleep(transaction_delay * 1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public void generateTransferActivity(double transaction_delay, int max_transactions) {
int txn_count = 0;
Decimal128 min_tik_id;
Decimal128 max_tik_id;
Decimal128 tik_id;
Decimal128 new_ticketholder;
boolean xfer_all;
boolean chg_price;
Decimal128 new_price;
while (txn_count < max_transactions) {
Document minMaxResult = db.getCollection("ticketPurchaseHist")
.aggregate(Arrays.asList(
Aggregates.group(null,
Accumulators.min("min_tik_id", "$sportingEventTicketId"),
Accumulators.max("max_tik_id", "$sportingEventTicketId")
)
)).first();
if (minMaxResult == null) {
System.out.println("No tickets available to transfer.");
return;
}
min_tik_id = minMaxResult.get("min_tik_id", Decimal128.class);
max_tik_id = minMaxResult.get("max_tik_id", Decimal128.class);
Document tikResult = db.getCollection("ticketPurchaseHist")
.aggregate(Arrays.asList(
Aggregates.match(Filters.lte("sportingEventTicketId", new Decimal128(Math.random() * (max_tik_id.doubleValue() - min_tik_id.doubleValue()) + min_tik_id.doubleValue()))),
Aggregates.group(null, Accumulators.max("tik_id", "$sportingEventTicketId"))
)).first();
if (tikResult == null) {
System.out.println("No tickets available to transfer.");
return;
}
tik_id = tikResult.get("tik_id", Decimal128.class);
new_ticketholder = new Decimal128(Math.floor(Math.random() * (g_max_person_id.doubleValue() - g_min_person_id.doubleValue()) + g_min_person_id.doubleValue()));
xfer_all = (Math.round(Math.random() * 4) < 4); // transfer all tickets 80% of the time
new_price = null;
chg_price = (Math.round(Math.random() * 2) == 0); // 30% of the time change price
if (chg_price) {
Document priceResult = db.getCollection("sportingEventTicket")
.find(Filters.eq("id", tik_id))
.projection(Projections.include("ticketPrice"))
.first();
if (priceResult != null) {
new_price = new Decimal128(priceResult.getDouble("ticketPrice") * (Math.random() * 0.4 + 0.8));
}
}
transferTicket(tik_id, new_ticketholder, xfer_all, new_price);
txn_count++;
try {
Thread.sleep((long) (transaction_delay * 1000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public List<Document> getOpenEvents() {
List<Document> eventTab = new ArrayList<>();
MongoCollection<Document> sportingEventCollection = db.getCollection("sportingEvent");
FindIterable<Document> openEvents = sportingEventCollection.find(Filters.eq("soldOut", 0))
.sort(Sorts.ascending("startDateTime"));
for (Document oeRec : openEvents) {
eventTab.add(oeRec);
}
return eventTab;
}
public eventRecType get_event_details(Number event_id) {
eventRecType eventRec = new eventRecType();
Number p_event_id = event_id;
List<Document> pipeline = Arrays.asList(
new Document("$match", new Document("id", p_event_id)),
new Document("$lookup", new Document("from", "sportTeam")
.append("localField", "homeTeamId")
.append("foreignField", "id")
.append("as", "home_team")),
new Document("$lookup", new Document("from", "sportTeam")
.append("localField", "awayTeamId")
.append("foreignField", "id")
.append("as", "away_team")),
new Document("$lookup", new Document("from", "sportLocation")
.append("localField", "locationId")
.append("foreignField", "id")
.append("as", "location")),
new Document("$unwind", "$home_team"),
new Document("$unwind", "$away_team"),
new Document("$unwind", "$location"),
new Document("$project", new Document("sport_name", "$sportTypeName")
.append("home_team_name", "$home_team.name")
.append("away_team_name", "$away_team.name")
.append("home_field", "$location.name")
.append("date_time", "$startDateTime"))
);
MongoCollection<Document> collection = db.getCollection("sportingEvent");
AggregateIterable<Document> result = collection.aggregate(pipeline);
Document doc = result.first();
if (doc != null) {
eventRec.sport_name = doc.getString("sport_name");
eventRec.home_team_name = doc.getString("home_team_name");
eventRec.away_team_name = doc.getString("away_team_name");
eventRec.home_field = doc.getString("home_field");
eventRec.date_time = doc.getDate("date_time");
}
return eventRec;
}
public void sellRandomTickets() {
List<Document> eventTab = getOpenEvents();
int rowCt = eventTab.size();
int eventIdx = (int) Math.floor(Math.random() * rowCt);
Document event = eventTab.get(eventIdx);
Decimal128 eventId = event.get("id", Decimal128.class);
Decimal128 ticketHolder = new Decimal128(Math.floor(Math.random() * (g_max_person_id.doubleValue() - g_min_person_id.doubleValue()) + g_min_person_id.doubleValue()));
int quantity = (int) Math.floor(Math.random() * 5) + 1;
sellTickets(ticketHolder, eventId, quantity);
}
public void transferTicket(int ticket_id, int new_ticketholder_id, boolean transfer_all, Double price) {
int p_ticket_id = ticket_id;
int p_new_ticketholder_id = new_ticketholder_id;
Double p_price = price;
int xferall = transfer_all ? 1 : 0;
int old_ticketholder_id;
Date last_txn_date;
List<Document> txfr_cur;
try {
Document result = db.getCollection("ticketPurchaseHist").aggregate(Arrays.asList(
Aggregates.match(Filters.eq("sportingEventTicketId", p_ticket_id)),
Aggregates.group("$ticketholderId", Accumulators.max("transaction_date_time", "$transactionDateTime")),
Aggregates.lookup("sportingEventTicket", "ticketholderId", "ticketholderId", "ticket"),
Aggregates.unwind("$ticket"),
Aggregates.match(Filters.or(
Filters.eq("ticket.id", p_ticket_id),
Filters.eq("xferall", 1)
)),
Aggregates.project(Projections.fields(
Projections.computed("transaction_date_time", "$transaction_date_time"),
Projections.computed("ticketholder_id", "$ticket.ticketholderId")
))
)).first();
if (result != null) {
last_txn_date = result.getDate("transaction_date_time");
old_ticketholder_id = result.getInteger("ticketholder_id");
txfr_cur = db.getCollection("ticketPurchaseHist").find(Filters.and(
Filters.eq("purchased_by_id", old_ticketholder_id),
Filters.eq("transaction_date_time", last_txn_date)
)).into(new ArrayList<>());
for (Document xrec : txfr_cur) {
db.getCollection("sportingEventTicket").updateOne(
Filters.eq("id", xrec.getInteger("sportingEventTicketId")),
Updates.set("ticketholder_id", p_new_ticketholder_id)
);
db.getCollection("ticketPurchaseHist").insertOne(new Document()
.append("sportingEventTicketId", xrec.getInteger("sportingEventTicketId"))
.append("purchased_by_id", p_new_ticketholder_id)
.append("transferred_from_id", old_ticketholder_id)
.append("transaction_date_time", new Date())
.append("purchase_price", p_price != null ? p_price : xrec.getDouble("purchase_price"))
);
}
}
db.getCollection("sportingEventTicket").getDatabase().runCommand(new Document("commitTransaction", 1));
} catch (Exception e) {
db.getCollection("sportingEventTicket").getDatabase().runCommand(new Document("abortTransaction", 1));
}
}
}

戻る

保存された手順の変換