Поиск последних записей в настройке NoSQL

#php #nosql

#php #nosql

Вопрос:

Я создал простой скрипт на PHP, который имеет две функции:

  • Дайте загруженному файлу UUID и временную метку, сохраните его на диске, используя UUID в качестве имени файла, верните UUID.
  • Извлеките и верните сохраненный файл с помощью UUID.

Я построил это без базы данных, поскольку требования были очень простыми, и из-за политики клиента / хостера настройка базы данных MySQL была бы утомительной.

Теперь появилось еще одно требование. Мне нужно добавить функцию, которая возвращает список X последних загруженных файлов, и, если возможно, добавить к нему разбивку на страницы.

Какой самый простой способ сделать это без MySQL? Или достаточно сложно гарантировать настройку базы данных?

Ответ №1:

Если это так просто, вы все равно можете использовать файлы. Вы можете сохранять временные метки в текстовом файле и извлекать из него последние n строк. Если вам нужно что-то более сложное, вы можете попробовать sqlite или Kyoto cabinet. Пока у вас не возникнет необходимость выразить отношения между некоторыми наборами данных, вы, вероятно, можете обойтись без реляционной базы данных.

Комментарии:

1. Да, я думал о записи идентификаторов в обычный текстовый файл, но это не произвольный доступ. Поиск последних 10 из списка из 1000 будет означать, что сначала будут пропущены 990 строк. На практике это может и не быть проблемой (я действительно не знаю, какую нагрузку на трафик ожидать), но это не совсем правильно.

Ответ №2:

Это мое решение. Я просто записываю идентификаторы новых загрузок в обычный текстовый файл. Поскольку каждый идентификатор равен ровно 37 байтам (36 n), файл становится доступным случайным образом. Я также использую flock , чтобы сделать его потокобезопасным.

 function gen_uuid() {
    return sprintf( 'xx-x-x-x-xxx',
        // 32 bits for "time_low"
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),

        // 16 bits for "time_mid"
        mt_rand( 0, 0xffff ),

        // 16 bits for "time_hi_and_version",
        // four most significant bits holds version number 4
        mt_rand( 0, 0x0fff ) | 0x4000,

        // 16 bits, 8 bits for "clk_seq_hi_res",
        // 8 bits for "clk_seq_low",
        // two most significant bits holds zero and one for variant DCE1.1
        mt_rand( 0, 0x3fff ) | 0x8000,

        // 48 bits for "node"
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
    );
}

// "constants"
$savedDir = dirname(__FILE__) . '/saved';
$orderedFile = dirname(__FILE__) . '/ordered.txt';

// prepare response
$resp = null;

// switch on action
$action = $_REQUEST['action'];
if ($action == 'saveVideo') {

    // read params
    $video = $_REQUEST['video'];
    $face = $_REQUEST['face'];

    // add current timestamp
    $date = time();

    // generate UUID
    $id = gen_uuid();

    // package data
    $pack = array(
        'id' => $id,
        'video' => $video,
        'face' => $face,
        'date' => $date
    );

    // save package using ID as filename
    file_put_contents($savedDir . '/' . $id, json_encode($pack));

    // write new ID to file with ordered IDs
    $f = fopen($orderedFile, 'a');
    if(flock($f, LOCK_EX)) {
        fseek($f, 0, SEEK_END);
        fwrite($f, $id . "n");
        flock($f, LOCK_UN);
    }
    fclose($f);

    $resp = array('id' => $id);


}

else if ($action == 'getLatestVideos') {

//  $debug = '';

    // parse parameters
    $amount = intval($_REQUEST['amount']);
    $start = intval($_REQUEST['start']);
//  $debug .= "amount $amount start $start";


    // find $amount latest IDs (skip $start)
    $ids = array();
    $f = fopen($orderedFile, 'r');
    if(flock($f, LOCK_SH)) {

        // get file size
        $fst = fstat($f);
        $fsize = $fst['size'];

        // determine IDs available
        $available = floor($fsize / 37);
//      $debug .= " available $available";

        if ($start < $available) {

            // determine amount to seek back
            $totamount = min($amount   $start, $available);
//          $debug .= " totamount $totamount";

            // seek back
            fseek($f, -37 * $totamount, SEEK_END);

            // now read forward until we have $amount (if could not seek back entirely, leave off the amount that would be sought back)
            for ($i = 0; $i < min($amount, $available-$start); $i  ) {

                // read ID
                $id = '';
                while(strlen($id) < 36) {
                    $id .= fread($f, 36 - strlen($id));
                }

                // skip n
                fseek($f, 1, SEEK_CUR);

                // add ID to list
                $ids[] = $id;

            }

        }

        flock($f, LOCK_UN);
    }
    fclose($f);

    // reverse IDs so list becomes from new to old
    $ids = array_reverse($ids);

    // get datas from IDs
    $resp = array();
    foreach ($ids as $id) {
        $resp[] = json_decode(file_get_contents($savedDir . '/' . $id));
    }

//  $resp[] = $debug;

}

else if ($action == 'getVideo') {

    // read and clean ID
    $id = strtolower($_REQUEST['id']);
    $id = preg_replace('/[^a-f0-9-]/', '', $id);

    // get data from ID
    $resp = json_decode(file_get_contents($savedDir . '/' . $id));

}

// unknown operation
else {
    $resp = 'Unknown action ' . $action;
}

// write response
echo json_encode($resp);