MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Menerapkan evaluasi objek ekspresi Query seperti goMongoDB

Pengantar

Saya pikir Mengevaluasi Kueri JSON seperti MongoDB di PHP telah memberikan semua Informasi yang Anda butuhkan. yang Anda butuhkan hanyalah berkreasi dengan solusi dan Anda mencapai apa yang Anda inginkan

Array

Mari kita asumsikan kita memiliki json yang mengikuti dikonversi ke larik

$json = '[{
    "name":"Mongo",
    "type":"db",
    "release":{
        "arch":"x86",
        "version":22,
        "year":2012
    }
},
{
    "name":"Mongo",
    "type":"db",
    "release":{
        "arch":"x64",
        "version":21,
        "year":2012
    }
},
{
    "name":"Mongo",
    "type":"db",
    "release":{
        "arch":"x86",
        "version":23,
        "year":2013
    }
},      
{
    "key":"Diffrent",
    "value":"cool",
    "children":{
        "tech":"json",
        "lang":"php",
        "year":2013
    }
}
]';

$array = json_decode($json, true);

Contoh 1

periksa apakah key - Different akan sesederhana

echo new ArrayCollection($array, array("key" => "Diffrent"));

Keluaran

{"3":{"key":"Diffrent","value":"cool","children":{"tech":"json","lang":"php","year":2013}}}

Contoh 2 Periksa apakah release year adalah 2013

echo new ArrayCollection($array, array("release.year" => 2013));

Keluaran

{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}

Contoh 3

Hitung di mana Year adalah 2012

$c = new ArrayCollection($array, array("release.year" => 2012));
echo count($c); // output 2 

Contoh 4

Mari kita ambil contoh di mana Anda ingin memeriksa version apakah grater than 22

$c = new ArrayCollection($array, array("release.version" => array('$gt'=>22)));
echo $c;

Keluaran

{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}

Contoh 5

Periksa apakah release.arch nilainya IN satu set seperti [x86,x100] (Contoh)

$c = new ArrayCollection($array, array("release.arch" => array('$in'=>array("x86","x100"))));
foreach($c as $var)
{
    print_r($var);
}

Keluaran

Array
(
    [name] => Mongo
    [type] => db
    [release] => Array
        (
            [arch] => x86
            [version] => 22
            [year] => 2012
        )

)
Array
(
    [name] => Mongo
    [type] => db
    [release] => Array
        (
            [arch] => x86
            [version] => 23
            [year] => 2013
        )

)

Contoh 6

Menggunakan

. yang Dapat Dipanggil
$year = 2013;
$expression = array("release.year" => array('$func' => function ($value) use($year) {
    return $value === 2013;
}));

$c = new ArrayCollection($array, $expression);

foreach ( $c as $var ) {
    print_r($var);
}

Keluaran

Array
(
    [name] => Mongo
    [type] => db
    [release] => Array
        (
            [arch] => x86
            [version] => 23
            [year] => 2013
        )

)

Contoh 7

Daftarkan nama ekspresi Anda sendiri

$c = new ArrayCollection($array, array("release.year" => array('$baba' => 3)), false);
$c->register('$baba', function ($a, $b) {
    return substr($a, - 1) == $b;
});
$c->parse();
echo $c;

Keluaran

{"2":{"name":"Mongo","type":"db","release":{"arch":"x86","version":23,"year":2013}}}

Kelas Digunakan

class ArrayCollection implements IteratorAggregate, Countable, JsonSerializable {
    private $array;
    private $found = array();
    private $log;
    private $expression;
    private $register;

    function __construct(array $array, array $expression, $parse = true) {
        $this->array = $array;
        $this->expression = $expression;
        $this->registerDefault();
        $parse === true and $this->parse();
    }

    public function __toString() {
        return $this->jsonSerialize();
    }

    public function jsonSerialize() {
        return json_encode($this->found);
    }

    public function getIterator() {
        return new ArrayIterator($this->found);
    }

    public function count() {
        return count($this->found);
    }

    public function getLog() {
        return $this->log;
    }

    public function register($offset, $value) {
        if (strpos($offset, '$') !== 0)
            throw new InvalidArgumentException('Expresiion name must always start with "$" sign');

        if (isset($this->register[$offset]))
            throw new InvalidArgumentException(sprintf('Expression %s already registred .. Please unregister It first'));

        if (! is_callable($value)) {
            throw new InvalidArgumentException(sprintf('Only callable value can be registred'));
        }

        $this->register[$offset] = $value;
    }

    public function unRegister($offset) {
        unset($this->register[$offset]);
    }

    public function parse() {
        $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($this->array));
        foreach ( $it as $k => $items ) {
            if ($this->evaluate($this->getPath($it), $items)) {
                $this->found[$it->getSubIterator(0)->key()] = $this->array[$it->getSubIterator(0)->key()];
            }
        }
    }

    private function registerDefault() {
        $this->register['$eq'] = array($this,"evaluateEqal");
        $this->register['$not'] = array($this,"evaluateNotEqual");

        $this->register['$gte'] = array($this,"evaluateGreater");
        $this->register['$gt'] = array($this,"evaluateGreater");

        $this->register['$lte'] = array($this,"evaluateLess");
        $this->register['$lt'] = array($this,"evaluateLess");

        $this->register['$in'] = array($this,"evalueateInset");

        $this->register['$func'] = array($this,"evalueateFunction");
        $this->register['$fn'] = array($this,"evalueateFunction");
        $this->register['$f'] = array($this,"evalueateFunction");
    }

    private function log($log) {
        $this->log[] = $log;
    }

    private function getPath(RecursiveIteratorIterator $it) {
        $keyPath = array();
        foreach ( range(1, $it->getDepth()) as $depth ) {
            $keyPath[] = $it->getSubIterator($depth)->key();
        }
        return implode(".", $keyPath);
    }

    private function checkType($a, $b) {
        if (gettype($a) != gettype($b)) {
            $this->log(sprintf("%s - %s  is not same type of %s - %s", json_encode($a), gettype($a), json_encode($b), gettype($b)));
            return false;
        }
        return true;
    }

    private function evaluate($key, $value) {
        $o = $r = 0; // Obigation & Requirement
        foreach ( $this->expression as $k => $options ) {
            if ($k !== $key)
                continue;

            if (is_array($options)) {
                foreach ( $options as $eK => $eValue ) {
                    if (strpos($eK, '$') === 0) {
                        $r ++;
                        $callable = $this->register[$eK];
                        $callable($value, $eValue) and $o ++;
                    } else {
                        throw new InvalidArgumentException('Missing "$" in expession key');
                    }
                }
            } else {

                $r ++;
                $this->evaluateEqal($value, $options) and $o ++;
            }
        }
        return $r > 0 && $o === $r;
    }

    private function evaluateEqal($a, $b) {
        return $a == $b;
    }

    private function evaluateNotEqual($a, $b) {
        return $a != $b;
    }

    private function evaluateLess($a, $b) {
        return $this->checkType($a, $b) and $a < $b;
    }

    private function evaluateGreater($a, $b) {
        return $this->checkType($a, $b) and $a > $b;
    }

    private function evalueateInset($a, array $b) {
        return in_array($a, $b);
    }

    private function evalueateFunction($a, callable $b) {
        return $b($a);
    }
}

Ringkasan

Ini mungkin tidak mencakup semua fitur lanjutan, dan harus memiliki arsitektur yang dapat diperluas

Kelas di atas menunjukkan contoh khas dari apa yang Anda inginkan .. Anda dapat dengan mudah decouple it , perluas untuk mendukung ekspresi majemuk seperti $and dan $or

Objek ekspresi kueri seperti MongoDB mudah untuk dipahami dan digunakan, memberikan kemampuan untuk menulis kode yang jelas dan bersih, karena kueri dan objek untuk ditelusuri, adalah array asosiatif.

Mengapa tidak menulis saja array ke MongoDB database daripada mengerjakannya dengan array ?? Ini lebih efisien dan akan menghemat banyak masalah

Saya juga harus menyebutkan bahwa menggunakan alat terbaik untuk pekerjaan terbaik ... Apa yang Anda inginkan pada dasarnya adalah fungsi dari Database

Pada dasarnya berbicara dengan fungsi yang mudah untuk mengekstrak informasi dari array php. Mengetahui struktur array(arrayPath), ini akan memungkinkan untuk melakukan operasi pada data array multidimensi, tanpa perlu beberapa loop bersarang.

Contoh menunjukkan bagaimana menggunakan jalur untuk mencari nilai tetapi Anda masih bergantung pada pemuatan larik ke memori dan kelas Anda melakukan beberapa rekursi dan loop yang tidak seefisien database .

Saya menghargai tips arsitektur, kode terkait atau serupa, yang mungkin merupakan contoh praktik yang baik untuk membangun ekspresi "if..else" php dengan cepat.

Apakah Anda benar-benar ingin semua itu ada di sini ???



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB:Apa itu penyatuan koneksi dan batas waktu?

  2. MongoDB - Beberapa $atau operasi

  3. Klien GUI MongoDB (lintas platform atau Linux)

  4. Masalah dengan MongoDB GridFS Menyimpan File dengan Node.JS

  5. Apa cara yang benar untuk memulai layanan mongod di linux / OS X?