0

I need to dynamically build a complex MongoDB query before executing it in PHP. My query line looks like $cursor = $c_sbc->aggregate($query_string);, where $query_string is something like [['$match' => ['symbol' => $sym]],['$project' => ['first' => ['$arrayElemAt' => ['$data.1000', -1]]]]].

Copy-and-pasting the above-given example to replace $query_string gives the desired result. However, running it with $query_string in place gives an error saying it expects an array, not a string. How do I get this query to work?

Catchable fatal error: Argument 1 passed to MongoDB\Collection::aggregate() must be of the type array, string given, called in C:\xampp\htdocs\gc5\screen.php on line 60 and defined in C:\xampp\htdocs\gc5\vendor\mongodb\mongodb\src\Collection.php on line 163

Edit: relevant PHP

$query = $_POST['screen'];

  $t = array(
    "revenue" => 1000,
    "costofgoodssold" => 1001
  );

  $data_array = [];

  //turn words into data.XXXX codes
  function translate($match){
    global $t;
    global $data_array;
    foreach($match as $m){
      $d = "data.".$t[$m];
      $data_array[] = $d;
      return $d;
    }
  }

  $query = preg_replace('/\s/', '', $query); //strip whitespace
  $query = strtolower($query);
  $query = preg_replace_callback('/([A-Z]+)/i','translate', $query);

  echo "<br>Query: ";
  print_r($query);
  echo "<br>";


  $client = new MongoDB\Client("mongodb://localhost:27017");
  $db = $client->gc_dev;
  $c_sbc = $db->screenByCompany;

  $for_years = [-1]; //default is TTM
  $symbols = ['goog', 'fb', 'crmt', 'vlgea', 'ko', 'pep', 'flws'];

  for($i=0;$i<count($symbols);$i++){
    $sym = $symbols[$i];
    for($j=0;$j<count($for_years);$j++){
      $k = $for_years[$j];

      //build query for data
      $data_query = "";
      foreach($data_array as $d){
        if($data_query == ""){ //first go-around, no need for comma
          $data_query .= "['first' => ['\$arrayElemAt' => ['$".$d."', ".$k."]]]";
        }else{
          //$data_query .= ",['second' => ['\$arrayElemAt' => ['$".$d."', ".$k."]]]";
        }
        $query_string = "[['\$match' => ['symbol' => \$sym]],['\$project' => ".$data_query."]]";

      }

      echo "<br>\$query_string: ".$query_string;
      $cursor = $c_sbc->aggregate($query_string);
      //$cursor = $c_sbc->aggregate([['$match' => ['symbol' => $sym]],['$project' => ['first' => ['$arrayElemAt' => ['$data.1000',-1]]]]]);
      $cursor = iterator_to_array($cursor);
      //var_dump($cursor);
      echo "Cursor: ".$cursor[0]['first'] . "<br><br>";

    }

Results in:

Query: (data.1000-data.1001)>1,000

$query_string: [['$match' => ['symbol' => $sym]],['$project' => ['first' => ['$arrayElemAt' => ['$data.1000', -1]]]]]

Catchable fatal error: Argument 1 passed to MongoDB\Collection::aggregate() must be of the type array, string given, called in C:\xampp\htdocs\gc5\screen.php on line 60 and defined in C:\xampp\htdocs\gc5\vendor\mongodb\mongodb\src\Collection.php on line 163
2
  • 1
    Try var_dump($query_string); before the $cursor =... call and make sure its what you expect. Commented Jul 29, 2016 at 23:11
  • 1
    Can you show the part of the code where you are defining $query_string ?? Commented Jul 29, 2016 at 23:13

1 Answer 1

1

Found your error. You are declaring $query_string as a string and not as an array like what the function aggregate is asking for. Your code is:

$query_string = "[['\$match' => ['symbol' => \$sym]],['\$project' => ".$data_query."]]";

Replace it with:

$query_string = [['\$match' => ['symbol' => \$sym]],['\$project' => $data_query]];

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.