From ecd4743c73014e4e191f4e36e04f6eec69f3827a Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 12:56:37 +0300 Subject: [PATCH 01/14] Create postgres dockerfile with jsquery --- .travis.yml | 31 -------- 9.2/Dockerfile | 59 --------------- 9.2/alpine/Dockerfile | 125 -------------------------------- 9.2/alpine/docker-entrypoint.sh | 123 ------------------------------- 9.2/docker-entrypoint.sh | 123 ------------------------------- 9.3/Dockerfile | 59 --------------- 9.3/alpine/Dockerfile | 125 -------------------------------- 9.3/alpine/docker-entrypoint.sh | 123 ------------------------------- 9.3/docker-entrypoint.sh | 123 ------------------------------- 9.4/Dockerfile | 59 --------------- 9.4/alpine/Dockerfile | 125 -------------------------------- 9.4/alpine/docker-entrypoint.sh | 123 ------------------------------- 9.4/docker-entrypoint.sh | 123 ------------------------------- 9.5/Dockerfile | 59 --------------- 9.5/alpine/Dockerfile | 125 -------------------------------- 9.5/alpine/docker-entrypoint.sh | 123 ------------------------------- 9.5/docker-entrypoint.sh | 123 ------------------------------- 9.6/Dockerfile | 2 +- 9.6/docker-entrypoint.sh | 11 ++- AUTHORS | 6 -- Dockerfile-alpine.template | 125 -------------------------------- Dockerfile-debian.template | 59 --------------- LICENSE | 22 ------ README.md | 24 +++--- docker-entrypoint.sh | 123 ------------------------------- generate-stackbrew-library.sh | 91 ----------------------- update.sh | 45 ------------ 27 files changed, 22 insertions(+), 2237 deletions(-) delete mode 100644 .travis.yml delete mode 100644 9.2/Dockerfile delete mode 100644 9.2/alpine/Dockerfile delete mode 100755 9.2/alpine/docker-entrypoint.sh delete mode 100755 9.2/docker-entrypoint.sh delete mode 100644 9.3/Dockerfile delete mode 100644 9.3/alpine/Dockerfile delete mode 100755 9.3/alpine/docker-entrypoint.sh delete mode 100755 9.3/docker-entrypoint.sh delete mode 100644 9.4/Dockerfile delete mode 100644 9.4/alpine/Dockerfile delete mode 100755 9.4/alpine/docker-entrypoint.sh delete mode 100755 9.4/docker-entrypoint.sh delete mode 100644 9.5/Dockerfile delete mode 100644 9.5/alpine/Dockerfile delete mode 100755 9.5/alpine/docker-entrypoint.sh delete mode 100755 9.5/docker-entrypoint.sh delete mode 100644 AUTHORS delete mode 100644 Dockerfile-alpine.template delete mode 100644 Dockerfile-debian.template delete mode 100644 LICENSE delete mode 100755 docker-entrypoint.sh delete mode 100755 generate-stackbrew-library.sh delete mode 100755 update.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9db325d0ca..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: bash -services: docker - -env: - - VERSION=9.6 - - VERSION=9.6 VARIANT=alpine - - VERSION=9.5 - - VERSION=9.5 VARIANT=alpine - - VERSION=9.4 - - VERSION=9.4 VARIANT=alpine - - VERSION=9.3 - - VERSION=9.3 VARIANT=alpine - - VERSION=9.2 - - VERSION=9.2 VARIANT=alpine - -install: - - git clone https://github.com/docker-library/official-images.git ~/official-images - -before_script: - - env | sort - - cd "$VERSION/$VARIANT" - - image="postgres:${VERSION}${VARIANT:+-${VARIANT}}" - -script: - - docker build -t "$image" . - - ~/official-images/test/run.sh "$image" - -after_script: - - docker images - -# vim:set et ts=2 sw=2: diff --git a/9.2/Dockerfile b/9.2/Dockerfile deleted file mode 100644 index b5b1c93a0a..0000000000 --- a/9.2/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -# vim:set ft=dockerfile: -FROM debian:jessie - -# explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres - -# grab gosu for easy step-down from root -ENV GOSU_VERSION 1.7 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 - -ENV PG_MAJOR 9.2 -ENV PG_VERSION 9.2.19-1.pgdg80+1 - -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list - -RUN apt-get update \ - && apt-get install -y postgresql-common \ - && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ - && apt-get install -y \ - postgresql-$PG_MAJOR=$PG_VERSION \ - postgresql-contrib-$PG_MAJOR=$PG_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# make the sample config easier to munge (and "correct by default") -RUN mv -v /usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample /usr/share/postgresql/$PG_MAJOR/ \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.2/alpine/Dockerfile b/9.2/alpine/Dockerfile deleted file mode 100644 index dc54d353cf..0000000000 --- a/9.2/alpine/Dockerfile +++ /dev/null @@ -1,125 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.4 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR 9.2 -ENV PG_VERSION 9.2.19 -ENV PG_SHA256 1d29d73a4f590fcc348280f13ac2ff6a0f72c94908c54e3c20b7ab1560e8dbad - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ - perl \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(getconf _NPROCESSORS_ONLN)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --recursive /usr/local \ - | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ - | sort -u \ - | xargs -r apk info --installed \ - | sort -u \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/include/* \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.2/alpine/docker-entrypoint.sh b/9.2/alpine/docker-entrypoint.sh deleted file mode 100755 index 2c87e77fb1..0000000000 --- a/9.2/alpine/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "su-exec postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | su-exec postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - su-exec postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec su-exec postgres "$@" -fi - -exec "$@" diff --git a/9.2/docker-entrypoint.sh b/9.2/docker-entrypoint.sh deleted file mode 100755 index 54a1098f7a..0000000000 --- a/9.2/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "gosu postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - gosu postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec gosu postgres "$@" -fi - -exec "$@" diff --git a/9.3/Dockerfile b/9.3/Dockerfile deleted file mode 100644 index 46ad744790..0000000000 --- a/9.3/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -# vim:set ft=dockerfile: -FROM debian:jessie - -# explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres - -# grab gosu for easy step-down from root -ENV GOSU_VERSION 1.7 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 - -ENV PG_MAJOR 9.3 -ENV PG_VERSION 9.3.15-1.pgdg80+1 - -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list - -RUN apt-get update \ - && apt-get install -y postgresql-common \ - && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ - && apt-get install -y \ - postgresql-$PG_MAJOR=$PG_VERSION \ - postgresql-contrib-$PG_MAJOR=$PG_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# make the sample config easier to munge (and "correct by default") -RUN mv -v /usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample /usr/share/postgresql/$PG_MAJOR/ \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.3/alpine/Dockerfile b/9.3/alpine/Dockerfile deleted file mode 100644 index 6e9886d9d3..0000000000 --- a/9.3/alpine/Dockerfile +++ /dev/null @@ -1,125 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.4 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR 9.3 -ENV PG_VERSION 9.3.15 -ENV PG_SHA256 a9fcba1446a93aa95e3e1b6535756f0472d10b0f267a0845f8b2b29f89de5c4f - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ - perl \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(getconf _NPROCESSORS_ONLN)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --recursive /usr/local \ - | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ - | sort -u \ - | xargs -r apk info --installed \ - | sort -u \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/include/* \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.3/alpine/docker-entrypoint.sh b/9.3/alpine/docker-entrypoint.sh deleted file mode 100755 index 2c87e77fb1..0000000000 --- a/9.3/alpine/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "su-exec postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | su-exec postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - su-exec postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec su-exec postgres "$@" -fi - -exec "$@" diff --git a/9.3/docker-entrypoint.sh b/9.3/docker-entrypoint.sh deleted file mode 100755 index 54a1098f7a..0000000000 --- a/9.3/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "gosu postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - gosu postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec gosu postgres "$@" -fi - -exec "$@" diff --git a/9.4/Dockerfile b/9.4/Dockerfile deleted file mode 100644 index 62d85c9548..0000000000 --- a/9.4/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -# vim:set ft=dockerfile: -FROM debian:jessie - -# explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres - -# grab gosu for easy step-down from root -ENV GOSU_VERSION 1.7 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 - -ENV PG_MAJOR 9.4 -ENV PG_VERSION 9.4.10-1.pgdg80+1 - -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list - -RUN apt-get update \ - && apt-get install -y postgresql-common \ - && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ - && apt-get install -y \ - postgresql-$PG_MAJOR=$PG_VERSION \ - postgresql-contrib-$PG_MAJOR=$PG_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# make the sample config easier to munge (and "correct by default") -RUN mv -v /usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample /usr/share/postgresql/$PG_MAJOR/ \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.4/alpine/Dockerfile b/9.4/alpine/Dockerfile deleted file mode 100644 index 7801d68746..0000000000 --- a/9.4/alpine/Dockerfile +++ /dev/null @@ -1,125 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.4 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR 9.4 -ENV PG_VERSION 9.4.10 -ENV PG_SHA256 7061678bed1981c681ce54c76b98b6ec17743f090a9775104a45e7e1a8826ecf - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ - perl \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(getconf _NPROCESSORS_ONLN)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --recursive /usr/local \ - | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ - | sort -u \ - | xargs -r apk info --installed \ - | sort -u \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/include/* \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.4/alpine/docker-entrypoint.sh b/9.4/alpine/docker-entrypoint.sh deleted file mode 100755 index 2c87e77fb1..0000000000 --- a/9.4/alpine/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "su-exec postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | su-exec postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - su-exec postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec su-exec postgres "$@" -fi - -exec "$@" diff --git a/9.4/docker-entrypoint.sh b/9.4/docker-entrypoint.sh deleted file mode 100755 index 54a1098f7a..0000000000 --- a/9.4/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "gosu postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - gosu postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec gosu postgres "$@" -fi - -exec "$@" diff --git a/9.5/Dockerfile b/9.5/Dockerfile deleted file mode 100644 index c9c0a283ca..0000000000 --- a/9.5/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -# vim:set ft=dockerfile: -FROM debian:jessie - -# explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres - -# grab gosu for easy step-down from root -ENV GOSU_VERSION 1.7 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 - -ENV PG_MAJOR 9.5 -ENV PG_VERSION 9.5.5-1.pgdg80+1 - -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list - -RUN apt-get update \ - && apt-get install -y postgresql-common \ - && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ - && apt-get install -y \ - postgresql-$PG_MAJOR=$PG_VERSION \ - postgresql-contrib-$PG_MAJOR=$PG_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# make the sample config easier to munge (and "correct by default") -RUN mv -v /usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample /usr/share/postgresql/$PG_MAJOR/ \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.5/alpine/Dockerfile b/9.5/alpine/Dockerfile deleted file mode 100644 index 6e8b1497e1..0000000000 --- a/9.5/alpine/Dockerfile +++ /dev/null @@ -1,125 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.4 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR 9.5 -ENV PG_VERSION 9.5.5 -ENV PG_SHA256 02c65290be74de6604c3fed87c9fd3e6b32e949f0ab8105a75bd7ed5aa71f394 - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ - perl \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(getconf _NPROCESSORS_ONLN)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --recursive /usr/local \ - | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ - | sort -u \ - | xargs -r apk info --installed \ - | sort -u \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/include/* \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.5/alpine/docker-entrypoint.sh b/9.5/alpine/docker-entrypoint.sh deleted file mode 100755 index 2c87e77fb1..0000000000 --- a/9.5/alpine/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "su-exec postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | su-exec postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - su-exec postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - su-exec postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec su-exec postgres "$@" -fi - -exec "$@" diff --git a/9.5/docker-entrypoint.sh b/9.5/docker-entrypoint.sh deleted file mode 100755 index 54a1098f7a..0000000000 --- a/9.5/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "gosu postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - gosu postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec gosu postgres "$@" -fi - -exec "$@" diff --git a/9.6/Dockerfile b/9.6/Dockerfile index 7a9169a0f8..15c17557f9 100644 --- a/9.6/Dockerfile +++ b/9.6/Dockerfile @@ -7,7 +7,7 @@ RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres # grab gosu for easy step-down from root ENV GOSU_VERSION 1.7 RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ + && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget git build-essential bison flex sudo && rm -rf /var/lib/apt/lists/* \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ && export GNUPGHOME="$(mktemp -d)" \ diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh index 54a1098f7a..095c8bc455 100755 --- a/9.6/docker-entrypoint.sh +++ b/9.6/docker-entrypoint.sh @@ -69,7 +69,7 @@ if [ "$1" = 'postgres' ]; then { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - # internal start of server in order to allow set-up using psql-client + # internal start of server in order to allow set-up using psql-client # does not listen on external TCP/IP and waits until start finishes gosu postgres pg_ctl -D "$PGDATA" \ -o "-c listen_addresses='localhost'" \ @@ -121,3 +121,12 @@ if [ "$1" = 'postgres' ]; then fi exec "$@" + +cd ~ +git config --global http.sslVerify false +git clone https://github.com/postgrespro/jsquery.git +cd jsquery +make USE_PGXS=1 +sudo make USE_PGXS=1 install +make USE_PGXS=1 installcheck +psql DB -c "CREATE EXTENSION jsquery;" diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index d3ad2447a2..0000000000 --- a/AUTHORS +++ /dev/null @@ -1,6 +0,0 @@ -Docker PostgreSQL Authors - -Tianon Gravi -Joseph Ferguson - -And other contributors not specifically named here. diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template deleted file mode 100644 index b012b7b560..0000000000 --- a/Dockerfile-alpine.template +++ /dev/null @@ -1,125 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.4 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR %%PG_MAJOR%% -ENV PG_VERSION %%PG_VERSION%% -ENV PG_SHA256 %%PG_SHA256%% - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ - perl \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(getconf _NPROCESSORS_ONLN)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --recursive /usr/local \ - | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ - | sort -u \ - | xargs -r apk info --installed \ - | sort -u \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/include/* \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template deleted file mode 100644 index 83eb859b98..0000000000 --- a/Dockerfile-debian.template +++ /dev/null @@ -1,59 +0,0 @@ -# vim:set ft=dockerfile: -FROM debian:jessie - -# explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres - -# grab gosu for easy step-down from root -ENV GOSU_VERSION 1.7 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 - -ENV PG_MAJOR %%PG_MAJOR%% -ENV PG_VERSION %%PG_VERSION%% - -RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list - -RUN apt-get update \ - && apt-get install -y postgresql-common \ - && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ - && apt-get install -y \ - postgresql-$PG_MAJOR=$PG_VERSION \ - postgresql-contrib-$PG_MAJOR=$PG_VERSION \ - && rm -rf /var/lib/apt/lists/* - -# make the sample config easier to munge (and "correct by default") -RUN mv -v /usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample /usr/share/postgresql/$PG_MAJOR/ \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres /var/run/postgresql - -ENV PATH /usr/lib/postgresql/$PG_MAJOR/bin:$PATH -ENV PGDATA /var/lib/postgresql/data -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh / - -ENTRYPOINT ["/docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4f324b2254..0000000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2014-2015, Docker PostgreSQL Authors (See AUTHORS) - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 3b0fa322ce..0c2234f155 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ -# About this Repo +# О репозитории -This is the Git repo of the Docker [official image](https://docs.docker.com/docker-hub/official_repos/) for [postgres](https://registry.hub.docker.com/_/postgres/). See [the Docker Hub page](https://registry.hub.docker.com/_/postgres/) for the full readme on how to use this Docker image and for information regarding contributing and issues. +Dockerfile для запуска PostgreSQL с установленным расширением jsquery. -The full readme is generated over in [docker-library/docs](https://github.com/docker-library/docs), specifically in [docker-library/docs/postgres](https://github.com/docker-library/docs/tree/master/postgres). +Для запуска на Windows 7 необходима версия VirtualBox > 5.1.10 -See a change merged here that doesn't show up on the Docker Hub yet? Check [the "library/postgres" manifest file in the docker-library/official-images repo](https://github.com/docker-library/official-images/blob/master/library/postgres), especially [PRs with the "library/postgres" label on that repo](https://github.com/docker-library/official-images/labels/library%2Fpostgres). For more information about the official images process, see the [docker-library/official-images readme](https://github.com/docker-library/official-images/blob/master/README.md). - ---- - -- [Travis CI: - ![build status badge](https://img.shields.io/travis/docker-library/postgres/master.svg)](https://travis-ci.org/docker-library/postgres/branches) -- [Automated `update.sh`: - ![build status badge](https://doi-janky.infosiftr.net/job/update.sh/job/postgres/badge/icon)](https://doi-janky.infosiftr.net/job/update.sh/job/postgres) - - +Комманда для запуска: +`docker build -t $IMAGENAME .` +`docker run --it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` +, где +`$IMAGENAME` - имя образа +`$CONTAINERNAME`- имя контейнера +`$PASSWORD` - пароль для доступа к базе +`$HOSTDIR` - адрес директории на устройстве, которая будет содержать данные и монтироваться к контейнеру diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index 54a1098f7a..0000000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chmod 700 "$PGDATA" - chown -R postgres "$PGDATA" - - mkdir -p /run/postgresql - chmod g+s /run/postgresql - chown -R postgres /run/postgresql - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - eval "gosu postgres initdb $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi - - { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - gosu postgres pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - fi - - exec gosu postgres "$@" -fi - -exec "$@" diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh deleted file mode 100755 index 4414b26235..0000000000 --- a/generate-stackbrew-library.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -set -eu - -declare -A aliases=( - [9.6]='9 latest' -) - -self="$(basename "$BASH_SOURCE")" -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - -versions=( */ ) -versions=( "${versions[@]%/}" ) - -# sort version numbers with highest first -IFS=$'\n'; versions=( $(echo "${versions[*]}" | sort -rV) ); unset IFS - -# get the most recent commit which modified any of "$@" -fileCommit() { - git log -1 --format='format:%H' HEAD -- "$@" -} - -# get the most recent commit which modified "$1/Dockerfile" or any file COPY'd from "$1/Dockerfile" -dirCommit() { - local dir="$1"; shift - ( - cd "$dir" - fileCommit \ - Dockerfile \ - $(git show HEAD:./Dockerfile | awk ' - toupper($1) == "COPY" { - for (i = 2; i < NF; i++) { - print $i - } - } - ') - ) -} - -cat <<-EOH -# this file is generated via https://github.com/docker-library/postgres/blob/$(fileCommit "$self")/$self - -Maintainers: Tianon Gravi (@tianon), - Joseph Ferguson (@yosifkit) -GitRepo: https://github.com/docker-library/postgres.git -EOH - -# prints "$2$1$3$1...$N" -join() { - local sep="$1"; shift - local out; printf -v out "${sep//%/%%}%s" "$@" - echo "${out#$sep}" -} - -for version in "${versions[@]}"; do - commit="$(dirCommit "$version")" - - fullVersion="$(git show "$commit":"$version/Dockerfile" | awk '$1 == "ENV" && $2 == "PG_VERSION" { gsub(/-.*$/, "", $3); gsub(/~/, "-", $3); print $3; exit }')" - - versionAliases=() - while [ "$fullVersion" != "$version" -a "${fullVersion%[.-]*}" != "$fullVersion" ]; do - versionAliases+=( $fullVersion ) - fullVersion="${fullVersion%[.-]*}" - done - versionAliases+=( - $version - ${aliases[$version]:-} - ) - - echo - cat <<-EOE - Tags: $(join ', ' "${versionAliases[@]}") - GitCommit: $commit - Directory: $version - EOE - - for variant in alpine; do - [ -f "$version/$variant/Dockerfile" ] || continue - - commit="$(dirCommit "$version/$variant")" - - variantAliases=( "${versionAliases[@]/%/-$variant}" ) - variantAliases=( "${variantAliases[@]//latest-/}" ) - - echo - cat <<-EOE - Tags: $(join ', ' "${variantAliases[@]}") - GitCommit: $commit - Directory: $version/$variant - EOE - done -done diff --git a/update.sh b/update.sh deleted file mode 100755 index c05525f8db..0000000000 --- a/update.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -set -eo pipefail - -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - -versions=( "$@" ) -if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) -fi -versions=( "${versions[@]%/}" ) - -packagesBase='http://apt.postgresql.org/pub/repos/apt/dists/jessie-pgdg' -mainList="$(curl -fsSL "$packagesBase/main/binary-amd64/Packages.bz2" | bunzip2)" - -travisEnv= -for version in "${versions[@]}"; do - versionList="$(echo "$mainList"; curl -fsSL "$packagesBase/$version/binary-amd64/Packages.bz2" | bunzip2)" - fullVersion="$(echo "$versionList" | awk -F ': ' '$1 == "Package" { pkg = $2 } $1 == "Version" && pkg == "postgresql-'"$version"'" { print $2; exit }' || true)" - ( - set -x - cp docker-entrypoint.sh "$version/" - sed 's/%%PG_MAJOR%%/'"$version"'/g; s/%%PG_VERSION%%/'"$fullVersion"'/g' Dockerfile-debian.template > "$version/Dockerfile" - ) - - # TODO figure out what to do with odd version numbers here, like release candidates - srcVersion="${fullVersion%%-*}" - srcSha256="$(curl -fsSL "https://ftp.postgresql.org/pub/source/v${srcVersion}/postgresql-${srcVersion}.tar.bz2.sha256" | cut -d' ' -f1)" - for variant in alpine; do - if [ ! -d "$version/$variant" ]; then - continue - fi - ( - set -x - cp docker-entrypoint.sh "$version/$variant/" - sed -i 's/gosu/su-exec/g' "$version/$variant/docker-entrypoint.sh" - sed 's/%%PG_MAJOR%%/'"$version"'/g; s/%%PG_VERSION%%/'"$srcVersion"'/g; s/%%PG_SHA256%%/'"$srcSha256"'/g' Dockerfile-$variant.template > "$version/$variant/Dockerfile" - ) - travisEnv="\n - VERSION=$version VARIANT=$variant$travisEnv" - done - - travisEnv='\n - VERSION='"$version$travisEnv" -done - -travis="$(awk -v 'RS=\n\n' '$1 == "env:" { $0 = "env:'"$travisEnv"'" } { printf "%s%s", $0, RS }' .travis.yml)" -echo "$travis" > .travis.yml From 80c63b1f9dc013122216ac2640ee9110e86e8e6b Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 12:58:33 +0300 Subject: [PATCH 02/14] Edits in Readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 0c2234f155..731d8ef42b 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,16 @@ Dockerfile для запуска PostgreSQL с установленным рас Для запуска на Windows 7 необходима версия VirtualBox > 5.1.10 Комманда для запуска: + `docker build -t $IMAGENAME .` + `docker run --it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` + , где `$IMAGENAME` - имя образа + `$CONTAINERNAME`- имя контейнера + `$PASSWORD` - пароль для доступа к базе + `$HOSTDIR` - адрес директории на устройстве, которая будет содержать данные и монтироваться к контейнеру From c01a5bd3abfe60166ee1bbcc0c28af8306cdabf4 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 15:48:42 +0300 Subject: [PATCH 03/14] Correct install jsquery --- 9.6/Dockerfile | 2 +- 9.6/docker-entrypoint.sh | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/9.6/Dockerfile b/9.6/Dockerfile index 15c17557f9..29a5c689d5 100644 --- a/9.6/Dockerfile +++ b/9.6/Dockerfile @@ -33,7 +33,7 @@ ENV PG_VERSION 9.6.1-2.pgdg80+1 RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list RUN apt-get update \ - && apt-get install -y postgresql-common \ + && apt-get install -y postgresql-common postgresql-server-dev-$PG_MAJOR \ && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \ && apt-get install -y \ postgresql-$PG_MAJOR=$PG_VERSION \ diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh index 095c8bc455..41352276c4 100755 --- a/9.6/docker-entrypoint.sh +++ b/9.6/docker-entrypoint.sh @@ -65,6 +65,7 @@ if [ "$1" = 'postgres' ]; then pass= authMethod=trust + exit fi { echo; echo "host all all all $authMethod"; } | gosu postgres tee -a "$PGDATA/pg_hba.conf" > /dev/null @@ -115,18 +116,23 @@ if [ "$1" = 'postgres' ]; then echo echo 'PostgreSQL init process complete; ready for start up.' echo + + fi - exec gosu postgres "$@" -fi + exec gosu postgres "$@" & + cd /home/ + git config --global http.sslVerify false + git clone https://github.com/postgrespro/jsquery.git + cd jsquery -exec "$@" + make USE_PGXS=1 + sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" + sudo make USE_PGXS=1 install + + make USE_PGXS=1 installcheck + psql postgres -c "CREATE EXTENSION jsquery;" + gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop +fi -cd ~ -git config --global http.sslVerify false -git clone https://github.com/postgrespro/jsquery.git -cd jsquery -make USE_PGXS=1 -sudo make USE_PGXS=1 install -make USE_PGXS=1 installcheck -psql DB -c "CREATE EXTENSION jsquery;" +exec gosu postgres "$@" From 272f9d5199e8924c0402245d1eb76b17c5aa191b Mon Sep 17 00:00:00 2001 From: Arinkin Nikita Date: Mon, 19 Dec 2016 16:24:18 +0300 Subject: [PATCH 04/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 731d8ef42b..bd5c63e252 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Dockerfile для запуска PostgreSQL с установленным рас `docker build -t $IMAGENAME .` -`docker run --it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` +`docker run -it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` , где `$IMAGENAME` - имя образа From fed2670a7320bdfb22bf51239085d8f80c0c7aa4 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 16:31:23 +0300 Subject: [PATCH 05/14] Added control if jsquery is alredy installed --- 9.6/docker-entrypoint.sh | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh index 41352276c4..98436002d5 100755 --- a/9.6/docker-entrypoint.sh +++ b/9.6/docker-entrypoint.sh @@ -120,19 +120,21 @@ if [ "$1" = 'postgres' ]; then fi - exec gosu postgres "$@" & - cd /home/ - git config --global http.sslVerify false - git clone https://github.com/postgrespro/jsquery.git - cd jsquery - - make USE_PGXS=1 - sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" - sudo make USE_PGXS=1 install - - make USE_PGXS=1 installcheck - psql postgres -c "CREATE EXTENSION jsquery;" - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop + if [ ! -d "$DIRECTORY" ]; then + exec gosu postgres "$@" & + cd /home/ + git config --global http.sslVerify false + git clone https://github.com/postgrespro/jsquery.git + cd jsquery + + make USE_PGXS=1 + sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" + sudo make USE_PGXS=1 install + + make USE_PGXS=1 installcheck + psql postgres -c "CREATE EXTENSION jsquery;" + gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop + fi fi exec gosu postgres "$@" From e0a5a383f93eee14aebd01af1b1b25a2f0ef8ae8 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 17:15:41 +0300 Subject: [PATCH 06/14] Checking if something exist --- 9.6/docker-entrypoint.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh index 98436002d5..883823cbf2 100755 --- a/9.6/docker-entrypoint.sh +++ b/9.6/docker-entrypoint.sh @@ -119,20 +119,23 @@ if [ "$1" = 'postgres' ]; then fi - - if [ ! -d "$DIRECTORY" ]; then + if [ ! -d "/home/jsquery" ]; then exec gosu postgres "$@" & + if !(sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='root'" | grep -q 1;) then + sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" + fi cd /home/ git config --global http.sslVerify false git clone https://github.com/postgrespro/jsquery.git cd jsquery make USE_PGXS=1 - sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" + sudo make USE_PGXS=1 install make USE_PGXS=1 installcheck - psql postgres -c "CREATE EXTENSION jsquery;" + psql postgres -c "CREATE EXTENSION IF NOT EXISTS jsquery;" + gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop fi fi From f03595394d98d8c52ef2fbaa92f62d8edc0d8627 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 19 Dec 2016 17:28:17 +0300 Subject: [PATCH 07/14] Repair errors on start --- 9.6/docker-entrypoint.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh index 883823cbf2..52ac8fe22b 100755 --- a/9.6/docker-entrypoint.sh +++ b/9.6/docker-entrypoint.sh @@ -121,7 +121,9 @@ if [ "$1" = 'postgres' ]; then fi if [ ! -d "/home/jsquery" ]; then exec gosu postgres "$@" & - if !(sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='root'" | grep -q 1;) then + if sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='root'" | grep -q 1; then + echo "root is already created" + else sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" fi cd /home/ From 75edd283e0780ecb9d62559f4c35a58381187959 Mon Sep 17 00:00:00 2001 From: Arinkin Nikita Date: Thu, 12 Jan 2017 11:21:42 +0300 Subject: [PATCH 08/14] Update Readme.md --- README.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index bd5c63e252..296cd3f57b 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,23 @@ # О репозитории -Dockerfile для запуска PostgreSQL с установленным расширением jsquery. +###Dockerfile для запуска PostgreSQL с установленным расширением jsquery. Для запуска на Windows 7 необходима версия VirtualBox > 5.1.10 -Комманда для запуска: +Образ на docker hub - https://hub.docker.com/r/nikozavr/postgresqlpro/ -`docker build -t $IMAGENAME .` +Последовательность команд для запуска: -`docker run -it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` +* Сборка образа из исходных кодов -, где -`$IMAGENAME` - имя образа + `docker build -t $IMAGENAME .` -`$CONTAINERNAME`- имя контейнера +* Запуск контейнера с использование собранного образа + + `docker run -it -d -p 5432:5432 --name=$CONTAINERNAME -e POSTGRES_PASSWORD=$PASSWORD -v $HOSTDIR:/var/lib/postgresql/data/ $IMAGENAME` -`$PASSWORD` - пароль для доступа к базе - -`$HOSTDIR` - адрес директории на устройстве, которая будет содержать данные и монтироваться к контейнеру + , где + * `$IMAGENAME` - имя образа + * `$CONTAINERNAME`- имя контейнера + * `$PASSWORD` - пароль для доступа к базе + * `$HOSTDIR` - адрес директории на устройстве, которая будет содержать данные и монтироваться к контейнеру From 9ac1485bf5d6852ef088a14d5ee8eeac9e7547b0 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Thu, 15 Feb 2018 13:35:57 +0300 Subject: [PATCH 09/14] Update posgresql disrt to 9.6.7 --- .gitmodules | 3 + 9.6/alpine/Dockerfile | 150 ---------------- 9.6/docker-entrypoint.sh | 169 ------------------ 9.6/Dockerfile => Dockerfile | 18 +- docker-entrypoint-initdb.d/init.sql | 1 + ...cker-entrypoint.sh => docker-entrypoint.sh | 5 +- jsquery | 1 + 7 files changed, 21 insertions(+), 326 deletions(-) create mode 100644 .gitmodules delete mode 100644 9.6/alpine/Dockerfile delete mode 100755 9.6/docker-entrypoint.sh rename 9.6/Dockerfile => Dockerfile (90%) create mode 100644 docker-entrypoint-initdb.d/init.sql rename 9.6/alpine/docker-entrypoint.sh => docker-entrypoint.sh (98%) mode change 100755 => 100644 create mode 160000 jsquery diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..d656f6da67 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "jsquery"] + path = jsquery + url = https://github.com/postgrespro/jsquery.git diff --git a/9.6/alpine/Dockerfile b/9.6/alpine/Dockerfile deleted file mode 100644 index 62f0167a67..0000000000 --- a/9.6/alpine/Dockerfile +++ /dev/null @@ -1,150 +0,0 @@ -# vim:set ft=dockerfile: -FROM alpine:3.5 - -# alpine includes "postgres" user/group in base install -# /etc/passwd:22:postgres:x:70:70::/var/lib/postgresql:/bin/sh -# /etc/group:34:postgres:x:70: -# the home directory for the postgres user, however, is not created by default -# see https://github.com/docker-library/postgres/issues/274 -RUN set -ex; \ - postgresHome="$(getent passwd postgres)"; \ - postgresHome="$(echo "$postgresHome" | cut -d: -f6)"; \ - [ "$postgresHome" = '/var/lib/postgresql' ]; \ - mkdir -p "$postgresHome"; \ - chown -R postgres:postgres "$postgresHome" - -# su-exec (gosu-compatible) is installed further down - -# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -# alpine doesn't require explicit locale-file generation -ENV LANG en_US.utf8 - -RUN mkdir /docker-entrypoint-initdb.d - -ENV PG_MAJOR 9.6 -ENV PG_VERSION 9.6.7 -ENV PG_SHA256 2ebe3df3c1d1eab78023bdc3ffa55a154aa84300416b075ef996598d78a624c6 - -RUN set -ex \ - \ - && apk add --no-cache --virtual .fetch-deps \ - ca-certificates \ - openssl \ - tar \ - \ - && wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2" \ - && echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c - \ - && mkdir -p /usr/src/postgresql \ - && tar \ - --extract \ - --file postgresql.tar.bz2 \ - --directory /usr/src/postgresql \ - --strip-components 1 \ - && rm postgresql.tar.bz2 \ - \ - && apk add --no-cache --virtual .build-deps \ - bison \ - coreutils \ - dpkg-dev dpkg \ - flex \ - gcc \ -# krb5-dev \ - libc-dev \ - libedit-dev \ - libxml2-dev \ - libxslt-dev \ - make \ -# openldap-dev \ - openssl-dev \ -# configure: error: prove not found - perl \ -# configure: error: Perl module IPC::Run is required to run TAP tests - perl-ipc-run \ -# perl-dev \ -# python-dev \ -# python3-dev \ -# tcl-dev \ - util-linux-dev \ - zlib-dev \ - \ - && cd /usr/src/postgresql \ -# update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) -# see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f - && awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new \ - && grep '/var/run/postgresql' src/include/pg_config_manual.h.new \ - && mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h \ - && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \ -# explicitly update autoconf config.guess and config.sub so they support more arches/libcs - && wget -O config/config.guess 'https://git.savannah.gnu.org/cgit/config.git/plain/config.guess?id=7d3d27baf8107b630586c962c057e22149653deb' \ - && wget -O config/config.sub 'https://git.savannah.gnu.org/cgit/config.git/plain/config.sub?id=7d3d27baf8107b630586c962c057e22149653deb' \ -# configure options taken from: -# https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 - && ./configure \ - --build="$gnuArch" \ -# "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" -# --enable-nls \ - --enable-integer-datetimes \ - --enable-thread-safety \ - --enable-tap-tests \ -# skip debugging info -- we want tiny size instead -# --enable-debug \ - --disable-rpath \ - --with-uuid=e2fs \ - --with-gnu-ld \ - --with-pgport=5432 \ - --with-system-tzdata=/usr/share/zoneinfo \ - --prefix=/usr/local \ - --with-includes=/usr/local/include \ - --with-libraries=/usr/local/lib \ - \ -# these make our image abnormally large (at least 100MB larger), which seems uncouth for an "Alpine" (ie, "small") variant :) -# --with-krb5 \ -# --with-gssapi \ -# --with-ldap \ -# --with-tcl \ -# --with-perl \ -# --with-python \ -# --with-pam \ - --with-openssl \ - --with-libxml \ - --with-libxslt \ - && make -j "$(nproc)" world \ - && make install-world \ - && make -C contrib install \ - \ - && runDeps="$( \ - scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ - | tr ',' '\n' \ - | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ - )" \ - && apk add --no-cache --virtual .postgresql-rundeps \ - $runDeps \ - bash \ - su-exec \ -# tzdata is optional, but only adds around 1Mb to image size and is recommended by Django documentation: -# https://docs.djangoproject.com/en/1.10/ref/databases/#optimizing-postgresql-s-configuration - tzdata \ - && apk del .fetch-deps .build-deps \ - && cd / \ - && rm -rf \ - /usr/src/postgresql \ - /usr/local/share/doc \ - /usr/local/share/man \ - && find /usr/local -name '*.a' -delete - -# make the sample config easier to munge (and "correct by default") -RUN sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample - -RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql - -ENV PGDATA /var/lib/postgresql/data -RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) -VOLUME /var/lib/postgresql/data - -COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat -ENTRYPOINT ["docker-entrypoint.sh"] - -EXPOSE 5432 -CMD ["postgres"] diff --git a/9.6/docker-entrypoint.sh b/9.6/docker-entrypoint.sh deleted file mode 100755 index ed319547f6..0000000000 --- a/9.6/docker-entrypoint.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env bash -set -e - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi - -# allow the container to be started with `--user` -if [ "$1" = 'postgres' ] && [ "$(id -u)" = '0' ]; then - mkdir -p "$PGDATA" - chown -R postgres "$PGDATA" - chmod 700 "$PGDATA" - - mkdir -p /var/run/postgresql - chown -R postgres /var/run/postgresql - chmod 775 /var/run/postgresql - - # Create the transaction log directory before initdb is run (below) so the directory is owned by the correct user - if [ "$POSTGRES_INITDB_XLOGDIR" ]; then - mkdir -p "$POSTGRES_INITDB_XLOGDIR" - chown -R postgres "$POSTGRES_INITDB_XLOGDIR" - chmod 700 "$POSTGRES_INITDB_XLOGDIR" - fi - - exec gosu postgres "$BASH_SOURCE" "$@" -fi - -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chown -R "$(id -u)" "$PGDATA" 2>/dev/null || : - chmod 700 "$PGDATA" 2>/dev/null || : - - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - if [ "$POSTGRES_INITDB_XLOGDIR" ]; then - export POSTGRES_INITDB_ARGS="$POSTGRES_INITDB_ARGS --xlogdir $POSTGRES_INITDB_XLOGDIR" - fi - eval "initdb --username=postgres $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - exit - fi - - { - echo - echo "host all all all $authMethod" - } >> "$PGDATA/pg_hba.conf" - - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - PGUSER="${PGUSER:-postgres}" \ - pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start - - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" - - psql=( psql -v ON_ERROR_STOP=1 ) - - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi - - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo - - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - PGUSER="${PGUSER:-postgres}" \ - pg_ctl -D "$PGDATA" -m fast -w stop - - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo - - - fi - if [ ! -d "/home/jsquery" ]; then - exec gosu postgres "$@" & - if sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='root'" | grep -q 1; then - echo "root is already created" - else - sudo -u postgres psql postgres -c "CREATE USER root WITH SUPERUSER PASSWORD '$POSTGRES_PASSWORD';" - fi - cd /home/ - git config --global http.sslVerify false - git clone https://github.com/postgrespro/jsquery.git - cd jsquery - - make USE_PGXS=1 - - sudo make USE_PGXS=1 install - - make USE_PGXS=1 installcheck - psql postgres -c "CREATE EXTENSION IF NOT EXISTS jsquery;" - - gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop - fi -fi - -exec gosu postgres "$@" diff --git a/9.6/Dockerfile b/Dockerfile similarity index 90% rename from 9.6/Dockerfile rename to Dockerfile index 421cc79bce..b6fe4dd9d8 100644 --- a/9.6/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN set -x \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ + && gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu \ @@ -33,7 +33,8 @@ RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 ENV LANG en_US.utf8 -RUN mkdir /docker-entrypoint-initdb.d +COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/ +#RUN mkdir /docker-entrypoint-initdb.d RUN set -ex; \ # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] @@ -41,7 +42,7 @@ RUN set -ex; \ # uid PostgreSQL Debian Repository key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ export GNUPGHOME="$(mktemp -d)"; \ - gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ + gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key"; \ gpg --export "$key" > /etc/apt/trusted.gpg.d/postgres.gpg; \ rm -rf "$GNUPGHOME"; \ apt-key list @@ -126,8 +127,17 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) VOLUME /var/lib/postgresql/data +COPY jsquery/ /opt/jsquery/ + +RUN apt-get update && apt-get install -y postgresql-server-dev-9.6 + +RUN cd /opt/jsquery \ + && make USE_PGXS=1 \ + && make USE_PGXS=1 install + COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat +RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \ + && ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 5432 diff --git a/docker-entrypoint-initdb.d/init.sql b/docker-entrypoint-initdb.d/init.sql new file mode 100644 index 0000000000..5989639227 --- /dev/null +++ b/docker-entrypoint-initdb.d/init.sql @@ -0,0 +1 @@ +CREATE EXTENSION jsquery; \ No newline at end of file diff --git a/9.6/alpine/docker-entrypoint.sh b/docker-entrypoint.sh old mode 100755 new mode 100644 similarity index 98% rename from 9.6/alpine/docker-entrypoint.sh rename to docker-entrypoint.sh index 4bc72cb6b4..c133583ab3 --- a/9.6/alpine/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -44,7 +44,7 @@ if [ "$1" = 'postgres' ] && [ "$(id -u)" = '0' ]; then chmod 700 "$POSTGRES_INITDB_XLOGDIR" fi - exec su-exec postgres "$BASH_SOURCE" "$@" + exec gosu postgres "$BASH_SOURCE" "$@" fi if [ "$1" = 'postgres' ]; then @@ -76,7 +76,6 @@ if [ "$1" = 'postgres' ]; then Docker's default configuration, this is effectively any other container on the same system. - Use "-e POSTGRES_PASSWORD=password" to set it in "docker run". **************************************************** @@ -142,4 +141,4 @@ if [ "$1" = 'postgres' ]; then fi fi -exec "$@" +exec "$@" \ No newline at end of file diff --git a/jsquery b/jsquery new file mode 160000 index 0000000000..580f6cb27c --- /dev/null +++ b/jsquery @@ -0,0 +1 @@ +Subproject commit 580f6cb27cd92b32c08d6f668652c35f042b1920 From bdf2378fd2d72e287e6d4fc341efdcc446d53002 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Fri, 17 Jul 2020 11:31:07 +0300 Subject: [PATCH 10/14] Update postgresql distributive to 12.3 --- Dockerfile | 237 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 92 deletions(-) diff --git a/Dockerfile b/Dockerfile index b6fe4dd9d8..3d2177ca9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,139 +1,192 @@ # vim:set ft=dockerfile: -FROM debian:jessie +FROM debian:buster-slim RUN set -ex; \ - if ! command -v gpg > /dev/null; then \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - fi + if ! command -v gpg > /dev/null; then \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gnupg \ + dirmngr \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + fi # explicitly set user/group IDs -RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres +RUN set -eux; \ + groupadd -r postgres --gid=999; \ +# https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 + useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ +# also create the postgres user's home directory with appropriate permissions +# see https://github.com/docker-library/postgres/issues/274 + mkdir -p /var/lib/postgresql; \ + chown -R postgres:postgres /var/lib/postgresql # grab gosu for easy step-down from root -ENV GOSU_VERSION 1.10 -RUN set -x \ - && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget git build-essential bison flex sudo && rm -rf /var/lib/apt/lists/* \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-get purge -y --auto-remove ca-certificates wget +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.12 +RUN set -eux; \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates wget; \ + rm -rf /var/lib/apt/lists/*; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default -RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ - && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +RUN set -eux; \ + if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ +# if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) + grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ + ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + fi; \ + apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 ENV LANG en_US.utf8 -COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/ -#RUN mkdir /docker-entrypoint-initdb.d +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ +# install "nss_wrapper" in case we need to fake "/etc/passwd" and "/etc/group" (especially for OpenShift) +# https://github.com/docker-library/postgres/issues/359 +# https://cwrap.org/nss_wrapper.html + libnss-wrapper \ +# install "xz-utils" for .sql.xz docker-entrypoint-initdb.d files + xz-utils \ + ; \ + rm -rf /var/lib/apt/lists/* + +RUN mkdir /docker-entrypoint-initdb.d RUN set -ex; \ # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 # uid PostgreSQL Debian Repository - key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key"; \ - gpg --export "$key" > /etc/apt/trusted.gpg.d/postgres.gpg; \ - rm -rf "$GNUPGHOME"; \ - apt-key list + key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ + gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/postgres.gpg; \ + command -v gpgconf > /dev/null && gpgconf --kill all; \ + rm -rf "$GNUPGHOME"; \ + apt-key list -ENV PG_MAJOR 9.6 -ENV PG_VERSION 9.6.7-1.pgdg80+1 +ENV PG_MAJOR 12 +ENV PG_VERSION 12.3-1.pgdg100+1 RUN set -ex; \ - \ - dpkgArch="$(dpkg --print-architecture)"; \ - case "$dpkgArch" in \ - amd64|i386|ppc64el) \ + \ +# see note below about "*.pyc" files + export PYTHONDONTWRITEBYTECODE=1; \ + \ + dpkgArch="$(dpkg --print-architecture)"; \ + case "$dpkgArch" in \ + amd64 | arm64 | i386 | ppc64el) \ # arches officialy built by upstream - echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ - apt-get update; \ - ;; \ - *) \ + echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ + apt-get update; \ + ;; \ + *) \ # we're on an architecture upstream doesn't officially build for # let's build binaries from their published source packages - echo "deb-src http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ - \ - tempDir="$(mktemp -d)"; \ - cd "$tempDir"; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - \ + echo "deb-src http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ + \ + case "$PG_MAJOR" in \ + 9.* | 10 ) ;; \ + *) \ +# https://github.com/docker-library/postgres/issues/484 (clang-6.0 required, only available in stretch-backports) +# TODO remove this once we hit buster+ + echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list.d/pgdg.list; \ + ;; \ + esac; \ + \ + tempDir="$(mktemp -d)"; \ + cd "$tempDir"; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + \ # build .deb files from upstream's source packages (which are verified by apt-get) - apt-get update; \ - apt-get build-dep -y \ - postgresql-common pgdg-keyring \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - ; \ - DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \ - apt-get source --compile \ - postgresql-common pgdg-keyring \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - ; \ + apt-get update; \ + apt-get build-dep -y \ + postgresql-common pgdg-keyring \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ + DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \ + apt-get source --compile \ + postgresql-common pgdg-keyring \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ # we don't remove APT lists here because they get re-downloaded and removed later - \ + \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) - apt-mark showmanual | xargs apt-mark auto > /dev/null; \ - apt-mark manual $savedAptMark; \ - \ + apt-mark showmanual | xargs apt-mark auto > /dev/null; \ + apt-mark manual $savedAptMark; \ + \ # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) - ls -lAFh; \ - dpkg-scanpackages . > Packages; \ - grep '^Package: ' Packages; \ - echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ + ls -lAFh; \ + dpkg-scanpackages . > Packages; \ + grep '^Package: ' Packages; \ + echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) # ... # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) - apt-get -o Acquire::GzipIndexes=false update; \ - ;; \ - esac; \ - \ - apt-get install -y postgresql-common; \ - sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ - apt-get install -y \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - "postgresql-contrib-$PG_MAJOR=$PG_VERSION" \ - ; \ - \ - rm -rf /var/lib/apt/lists/*; \ - \ - if [ -n "$tempDir" ]; then \ + apt-get -o Acquire::GzipIndexes=false update; \ + ;; \ + esac; \ + \ + apt-get install -y --no-install-recommends postgresql-common; \ + sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ + apt-get install -y --no-install-recommends \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ + \ + rm -rf /var/lib/apt/lists/*; \ + \ + if [ -n "$tempDir" ]; then \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) - apt-get purge -y --auto-remove; \ - rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ - fi + apt-get purge -y --auto-remove; \ + rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi; \ + \ +# some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) + find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' + # make the sample config easier to munge (and "correct by default") -RUN mv -v "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample" /usr/share/postgresql/ \ - && ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/" \ - && sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample +RUN set -eux; \ + dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ + cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ + ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ + sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ + grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin ENV PGDATA /var/lib/postgresql/data -RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) +# this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) +RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" VOLUME /var/lib/postgresql/data COPY jsquery/ /opt/jsquery/ -RUN apt-get update && apt-get install -y postgresql-server-dev-9.6 +RUN apt-get update && apt-get install -y build-essential bison flex postgresql-server-dev-12 RUN cd /opt/jsquery \ - && make USE_PGXS=1 \ - && make USE_PGXS=1 install + && make USE_PGXS=1 \ + && make USE_PGXS=1 install COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \ @@ -141,4 +194,4 @@ RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \ ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 5432 -CMD ["postgres"] +CMD ["postgres"] \ No newline at end of file From 1b960420fc26a5fc4afa28b776aaded44fd70d52 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Tue, 17 Nov 2020 11:53:45 +0300 Subject: [PATCH 11/14] Fix postgresql dev package Update postgresql distributive to 13.1 Remove jsquery as submodule Delete jsquery dir Add jsquery without submodule Rename PG_GETARG_JSONB to PG_GETARG_JSONB_P --- .gitmodules | 3 - Dockerfile | 38 +- jsquery | 1 - jsquery/.travis.yml | 35 + jsquery/META.json | 53 + jsquery/Makefile | 45 + jsquery/README.md | 357 +++ jsquery/data/test_jsquery.data | 1034 +++++++++ jsquery/expected/jsquery.out | 2923 +++++++++++++++++++++++++ jsquery/jsonb_gin_ops.c | 1353 ++++++++++++ jsquery/jsquery--1.0.sql | 293 +++ jsquery/jsquery.control | 6 + jsquery/jsquery.h | 249 +++ jsquery/jsquery_constr.c | 260 +++ jsquery/jsquery_extract.c | 1021 +++++++++ jsquery/jsquery_gram.y | 364 +++ jsquery/jsquery_io.c | 403 ++++ jsquery/jsquery_op.c | 1009 +++++++++ jsquery/jsquery_scan.l | 508 +++++ jsquery/jsquery_support.c | 251 +++ jsquery/sql/jsquery.sql | 548 +++++ jsquery/travis/dep-ubuntu-llvm.sh | 4 + jsquery/travis/dep-ubuntu-postgres.sh | 4 + jsquery/travis/llvm-snapshot.gpg.key | 52 + jsquery/travis/pg-travis-test.sh | 95 + jsquery/travis/postgresql.gpg.key | 77 + 26 files changed, 10979 insertions(+), 7 deletions(-) delete mode 100644 .gitmodules delete mode 160000 jsquery create mode 100644 jsquery/.travis.yml create mode 100644 jsquery/META.json create mode 100644 jsquery/Makefile create mode 100644 jsquery/README.md create mode 100644 jsquery/data/test_jsquery.data create mode 100644 jsquery/expected/jsquery.out create mode 100644 jsquery/jsonb_gin_ops.c create mode 100644 jsquery/jsquery--1.0.sql create mode 100644 jsquery/jsquery.control create mode 100644 jsquery/jsquery.h create mode 100644 jsquery/jsquery_constr.c create mode 100644 jsquery/jsquery_extract.c create mode 100644 jsquery/jsquery_gram.y create mode 100644 jsquery/jsquery_io.c create mode 100644 jsquery/jsquery_op.c create mode 100644 jsquery/jsquery_scan.l create mode 100644 jsquery/jsquery_support.c create mode 100644 jsquery/sql/jsquery.sql create mode 100644 jsquery/travis/dep-ubuntu-llvm.sh create mode 100644 jsquery/travis/dep-ubuntu-postgres.sh create mode 100644 jsquery/travis/llvm-snapshot.gpg.key create mode 100644 jsquery/travis/pg-travis-test.sh create mode 100644 jsquery/travis/postgresql.gpg.key diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d656f6da67..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "jsquery"] - path = jsquery - url = https://github.com/postgrespro/jsquery.git diff --git a/Dockerfile b/Dockerfile index 3d2177ca9e..b2a1680fa2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -82,8 +82,8 @@ RUN set -ex; \ rm -rf "$GNUPGHOME"; \ apt-key list -ENV PG_MAJOR 12 -ENV PG_VERSION 12.3-1.pgdg100+1 +ENV PG_MAJOR 13 +ENV PG_VERSION 13.1-1.pgdg100+1 RUN set -ex; \ \ @@ -118,6 +118,8 @@ RUN set -ex; \ \ # build .deb files from upstream's source packages (which are verified by apt-get) apt-get update; \ + # we need DEBIAN_FRONTEND on postgresql-13 for slapd ("Please enter the password for the admin entry in your LDAP directory."); see https://bugs.debian.org/929417 + DEBIAN_FRONTEND=noninteractive \ apt-get build-dep -y \ postgresql-common pgdg-keyring \ "postgresql-$PG_MAJOR=$PG_VERSION" \ @@ -182,7 +184,7 @@ VOLUME /var/lib/postgresql/data COPY jsquery/ /opt/jsquery/ -RUN apt-get update && apt-get install -y build-essential bison flex postgresql-server-dev-12 +RUN apt-get update && apt-get install -y build-essential bison flex postgresql-server-dev-13 RUN cd /opt/jsquery \ && make USE_PGXS=1 \ @@ -193,5 +195,35 @@ RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \ && ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat ENTRYPOINT ["docker-entrypoint.sh"] +# We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL +# calls "Fast Shutdown mode" wherein new connections are disallowed and any +# in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and +# flush tables to disk, which is the best compromise available to avoid data +# corruption. +# +# Users who know their applications do not keep open long-lived idle connections +# may way to use a value of SIGTERM instead, which corresponds to "Smart +# Shutdown mode" in which any existing sessions are allowed to finish and the +# server stops when all sessions are terminated. +# +# See https://www.postgresql.org/docs/12/server-shutdown.html for more details +# about available PostgreSQL server shutdown signals. +# +# See also https://www.postgresql.org/docs/12/server-start.html for further +# justification of this as the default value, namely that the example (and +# shipped) systemd service files use the "Fast Shutdown mode" for service +# termination. +# +STOPSIGNAL SIGINT +# +# An additional setting that is recommended for all users regardless of this +# value is the runtime "--stop-timeout" (or your orchestrator/runtime's +# equivalent) for controlling how long to wait between sending the defined +# STOPSIGNAL and sending SIGKILL (which is likely to cause data corruption). +# +# The default in most runtimes (such as Docker) is 10 seconds, and the +# documentation at https://www.postgresql.org/docs/12/server-start.html notes +# that even 90 seconds may not be long enough in many instances. + EXPOSE 5432 CMD ["postgres"] \ No newline at end of file diff --git a/jsquery b/jsquery deleted file mode 160000 index 580f6cb27c..0000000000 --- a/jsquery +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 580f6cb27cd92b32c08d6f668652c35f042b1920 diff --git a/jsquery/.travis.yml b/jsquery/.travis.yml new file mode 100644 index 0000000000..2f24ce5a96 --- /dev/null +++ b/jsquery/.travis.yml @@ -0,0 +1,35 @@ +os: + - linux + +sudo: required +dist: trusty + +language: c + +compiler: + - clang + - gcc + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -y install -qq wget ca-certificates; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source ./travis/dep-ubuntu-postgres.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source ./travis/dep-ubuntu-llvm.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi + +env: + global: + - LLVM_VER=4.0 + matrix: + - PG_VER=10 CHECK_CODE=true + - PG_VER=10 CHECK_CODE=false + - PG_VER=9.6 CHECK_CODE=true + - PG_VER=9.6 CHECK_CODE=false + - PG_VER=9.5 CHECK_CODE=true + - PG_VER=9.5 CHECK_CODE=false + - PG_VER=9.4 CHECK_CODE=true + - PG_VER=9.4 CHECK_CODE=false + +script: bash ./travis/pg-travis-test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/jsquery/META.json b/jsquery/META.json new file mode 100644 index 0000000000..694210c9de --- /dev/null +++ b/jsquery/META.json @@ -0,0 +1,53 @@ +{ + "name": "JsQuery", + "abstract": "JSON Query Language with GIN indexing support", + "description": "JsQuery provides additional functionality for JSONB, such as a simple and effective way to search in nested objects and arrays, and more comparison operators with index support. It does this by implementing a specialized search syntax, the @@ operator, and the jsquery type for search strings.", + "version": "1.0.1", + "maintainer": [ + "Teodor Sigaev ", + "Alexander Korotkov ", + "Oleg Bartunov " + ], + "license": { + "PostgreSQL": "http://www.postgresql.org/about/licence" + }, + "prereqs": { + "runtime": { + "requires": { + "PostgreSQL": "9.4.0" + }, + "recommends": { + "PostgreSQL": "9.6.5" + } + } + }, + "provides": { + "jsquery": { + "file": "sql/jsquery.sql", + "docfile": "README.md", + "version": "1.0.1", + "abstract": "JSON query language with GIN indexing support" + } + }, + "resources": { + "homepage": "https://github.com/postgrespro/jsquery", + "bugtracker": { + "web": "https://github.com/postgrespro/jsquery/issues" + }, + "repository": { + "url": "https://github.com/postgrespro/jsquery.git", + "web": "https://github.com/postgrespro/jsquery", + "type": "git" + } + }, + "generated_by": "Josh Berkus", + "meta-spec": { + "version": "1.0.0", + "url": "http://pgxn.org/meta/spec.txt" + }, + "tags": [ + "JSON", + "index", + "search" + ] +} \ No newline at end of file diff --git a/jsquery/Makefile b/jsquery/Makefile new file mode 100644 index 0000000000..d7d415c8a3 --- /dev/null +++ b/jsquery/Makefile @@ -0,0 +1,45 @@ +# contrib/jsquery/Makefile + +MODULE_big = jsquery +OBJS = jsonb_gin_ops.o jsquery_constr.o jsquery_extract.o \ + jsquery_gram.o jsquery_io.o jsquery_op.o jsquery_support.o + +EXTENSION = jsquery +DATA = jsquery--1.0.sql +INCLUDES = jsquery.h + +REGRESS = jsquery +# We need a UTF8 database +ENCODING = UTF8 + +EXTRA_CLEAN = y.tab.c y.tab.h \ + jsquery_gram.c jsquery_scan.c jsquery_gram.h + +ifdef USE_PGXS +PG_CONFIG ?= pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/jsquery +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +ifdef USE_ASSERT_CHECKING +override CFLAGS += -DUSE_ASSERT_CHECKING +endif + +jsquery_gram.o: jsquery_scan.c + +jsquery_gram.c: BISONFLAGS += -d + +distprep: jsquery_gram.c jsquery_scan.c + +maintainer-clean: + rm -f jsquery_gram.c jsquery_scan.c jsquery_gram.h + +install: installincludes + +installincludes: + $(INSTALL_DATA) $(addprefix $(srcdir)/, $(INCLUDES)) '$(DESTDIR)$(includedir_server)/' diff --git a/jsquery/README.md b/jsquery/README.md new file mode 100644 index 0000000000..3ce8dc83ac --- /dev/null +++ b/jsquery/README.md @@ -0,0 +1,357 @@ +[![Build Status](https://travis-ci.org/postgrespro/jsquery.svg?branch=master)](https://travis-ci.org/postgrespro/jsquery) +[![codecov](https://codecov.io/gh/postgrespro/jsquery/branch/master/graph/badge.svg)](https://codecov.io/gh/postgrespro/jsquery) + +JsQuery – json query language with GIN indexing support +======================================================= + +Introduction +------------ + +JsQuery – is a language to query jsonb data type, introduced in PostgreSQL +release 9.4. + +It's primary goal is to provide an additional functionality to jsonb +(currently missing in PostgreSQL), such as a simple and effective way +to search in nested objects and arrays, more comparison operators with +indexes support. We hope, that jsquery will be eventually a part of +PostgreSQL. + +Jsquery is released as jsquery data type (similar to tsquery) and @@ +match operator for jsonb. + +Authors +------- + + * Teodor Sigaev , Postgres Professional, Moscow, Russia + * Alexander Korotkov , Postgres Professional, Moscow, Russia + * Oleg Bartunov , Postgres Professional, Moscow, Russia + +Availability +------------ + +JsQuery is realized as an extension and not available in default PostgreSQL +installation. It is available from +[github](https://github.com/postgrespro/jsquery) +under the same license as +[PostgreSQL](https://www.postgresql.org/about/licence/) +and supports PostgreSQL 9.4+. + +Regards +------- + +Development was sponsored by [Wargaming.net](http://wargaming.net). + +Installation +------------ + +JsQuery is PostgreSQL extension which requires PostgreSQL 9.4 or higher. +Before build and install you should ensure following: + + * PostgreSQL version is 9.4 or higher. + * You have development package of PostgreSQL installed or you built + PostgreSQL from source. + * You have flex and bison installed on your system. JsQuery was tested on + flex 2.5.37-2.5.39, bison 2.7.12. + * Your PATH variable is configured so that pg\_config command available, or set PG_CONFIG variable. + +Typical installation procedure may look like this: + + $ git clone https://github.com/postgrespro/jsquery.git + $ cd jsquery + $ make USE_PGXS=1 + $ sudo make USE_PGXS=1 install + $ make USE_PGXS=1 installcheck + $ psql DB -c "CREATE EXTENSION jsquery;" + +JSON query language +------------------- + +JsQuery extension contains `jsquery` datatype which represents whole JSON query +as a single value (like `tsquery` does for fulltext search). The query is an +expression on JSON-document values. + +Simple expression is specified as `path binary_operator value` or +`path unary_operator`. See following examples. + + * `x = "abc"` – value of key "x" is equal to "abc"; + * `$ @> [4, 5, "zzz"]` – the JSON document is an array containing values + 4, 5 and "zzz"; + * `"abc xyz" >= 10` – value of key "abc xyz" is greater than or equal to 10; + * `volume IS NUMERIC` – type of key "volume" is numeric. + * `$ = true` – the whole JSON document is just a true. + * `similar_ids.@# > 5` – similar\_ids is an array or object of length greater + than 5; + * `similar_product_ids.# = "0684824396"` – array "similar\_product\_ids" + contains string "0684824396". + * `*.color = "red"` – there is object somewhere which key "color" has value + "red". + * `foo = *` – key "foo" exists in object. + +Path selects set of JSON values to be checked using given operators. In +the simplest case path is just an key name. In general path is key names and +placeholders combined by dot signs. Path can use following placeholders: + + * `#` – any index of array; + * `#N` – N-th index of array; + * `%` – any key of object; + * `*` – any sequence of array indexes and object keys; + * `@#` – length of array or object, could be only used as last component of + path; + * `$` – the whole JSON document as single value, could be only the whole path. + +Expression is true when operator is true against at least one value selected +by path. + +Key names could be given either with or without double quotes. Key names +without double quotes shouldn't contain spaces, start with number or concur +with jsquery keyword. + +The supported binary operators are: + + * Equality operator: `=`; + * Numeric comparison operators: `>`, `>=`, `<`, `<=`; + * Search in the list of scalar values using `IN` operator; + * Array comparison operators: `&&` (overlap), `@>` (contains), + `<@` (contained in). + +The supported unary operators are: + + * Check for existence operator: `= *`; + * Check for type operators: `IS ARRAY`, `IS NUMERIC`, `IS OBJECT`, `IS STRING` + and `IS BOOLEAN`. + +Expressions could be complex. Complex expression is a set of expressions +combined by logical operators (`AND`, `OR`, `NOT`) and grouped using braces. + +Examples of complex expressions are given below. + + * `a = 1 AND (b = 2 OR c = 3) AND NOT d = 1` + * `x.% = true OR x.# = true` + +Prefix expressions are expressions given in the form path (subexpression). +In this case path selects JSON values to be checked using given subexpression. +Check results are aggregated in the same way as in simple expressions. + + * `#(a = 1 AND b = 2)` – exists element of array which a key is 1 and b key is 2 + * `%($ >= 10 AND $ <= 20)` – exists object key which values is between 10 and 20 + +Path also could contain following special placeholders with "every" semantics: + + * `#:` – every indexes of array; + * `%:` – every key of object; + * `*:` – every sequence of array indexes and object keys. + +Consider following example. + + %.#:($ >= 0 AND $ <= 1) + +This example could be read as following: there is at least one key which value +is array of numerics between 0 and 1. + +We can rewrite this example in the following form with extra braces. + + %(#:($ >= 0 AND $ <= 1)) + +The first placeholder `%` checks that expression in braces is true for at least +one value in object. The second placeholder `#:` checks value to be array and +all its elements satisfy expressions in braces. + +We can rewrite this example without `#:` placeholder as follows. + + %(NOT #(NOT ($ >= 0 AND $ <= 1)) AND $ IS ARRAY) + +In this example we transform assertion that every element of array satisfy some +condition to assertion that there is no one element which doesn't satisfy the +same condition. + +Some examples of using paths are given below. + + * `numbers.#: IS NUMERIC` – every element of "numbers" array is numeric. + * `*:($ IS OBJECT OR $ IS BOOLEAN)` – JSON is a structure of nested objects + with booleans as leaf values. + * `#:.%:($ >= 0 AND $ <= 1)` – each element of array is object containing + only numeric values between 0 and 1. + * `documents.#:.% = *` – "documents" is array of objects containing at least + one key. + * `%.#: ($ IS STRING)` – JSON object contains at least one array of strings. + * `#.% = true` – at least one array element is objects which contains at least + one "true" value. + +Usage of path operators and braces need some explanation. When same path +operators are used multiple times they may refer different values while you can +refer same value multiple time by using braces and `$` operator. See following +examples. + + * `# < 10 AND # > 20` – exists element less than 10 and exists another element + greater than 20. + * `#($ < 10 AND $ > 20)` – exists element which both less than 10 and greater + than 20 (impossible). + * `#($ >= 10 AND $ <= 20)` – exists element between 10 and 20. + * `# >= 10 AND # <= 20` – exists element great or equal to 10 and exists + another element less or equal to 20. Query can be satisfied by array with + no elements between 10 and 20, for instance [0,30]. + +Same rules apply when you search inside objects and branchy structures. + +Type checking operators and "every" placeholders are useful for document +schema validation. JsQuery matchig operator `@@` is immutable and can be used +in CHECK constraint. See following example. + +```sql +CREATE TABLE js ( + id serial, + data jsonb, + CHECK (data @@ ' + name IS STRING AND + similar_ids.#: IS NUMERIC AND + points.#:(x IS NUMERIC AND y IS NUMERIC)'::jsquery)); +``` + +In this example check constraint validates that in "data" jsonb column: +value of "name" key is string, value of "similar_ids" key is array of numerics, +value of "points" key is array of objects which contain numeric values in +"x" and "y" keys. + +See our +[pgconf.eu presentation](http://www.sai.msu.su/~megera/postgres/talks/pgconfeu-2014-jsquery.pdf) +for more examples. + +GIN indexes +----------- + +JsQuery extension contains two operator classes (opclasses) for GIN which +provide different kinds of query optimization. + + * jsonb\_path\_value\_ops + * jsonb\_value\_path\_ops + +In each of two GIN opclasses jsonb documents are decomposed into entries. Each +entry is associated with particular value and it's path. Difference between +opclasses is in the entry representation, comparison and usage for search +optimization. + +For example, jsonb document +`{"a": [{"b": "xyz", "c": true}, 10], "d": {"e": [7, false]}}` +would be decomposed into following entries: + + * "a".#."b"."xyz" + * "a".#."c".true + * "a".#.10 + * "d"."e".#.7 + * "d"."e".#.false + +Since JsQuery doesn't support search in particular array index, we consider +all array elements to be equivalent. Thus, each array element is marked with +same `#` sign in the path. + +Major problem in the entries representation is its size. In the given example +key "a" is presented three times. In the large branchy documents with long +keys size of naive entries representation becomes unreasonable. Both opclasses +address this issue but in a slightly different way. + +### jsonb\_path\_value\_ops + +jsonb\_path\_value\_ops represents entry as pair of path hash and value. +Following pseudocode illustrates it. + + (hash(path_item_1.path_item_2. ... .path_item_n); value) + +In comparison of entries path hash is the higher part of entry and value is +its lower part. This determines the features of this opclass. Since path +is hashed and it is higher part of entry we need to know the full path to +the value in order to use it for search. However, once path is specified +we can use both exact and range searches very efficiently. + +### jsonb\_value\_path\_ops + +jsonb\_value\_path\_ops represents entry as pair of value and bloom filter +of path. + + (value; bloom(path_item_1) | bloom(path_item_2) | ... | bloom(path_item_n)) + +In comparison of entries value is the higher part of entry and bloom filter of +path is its lower part. This determines the features of this opclass. Since +value is the higher part of entry we can perform only exact value search +efficiently. Range value search is possible as well but we would have to +filter all the the different paths where matching values occur. Bloom filter +over path items allows index usage for conditions containing `%` and `*` in +their paths. + +### Query optimization + +JsQuery opclasses perform complex query optimization. Thus it's valuable for +developer or administrator to see the result of such optimization. +Unfortunately, opclasses aren't allowed to do any custom output to the +EXPLAIN. That's why JsQuery provides following functions which allows to see +how particular opclass optimizes given query. + + * gin\_debug\_query\_path\_value(jsquery) – for jsonb\_path\_value\_ops + * gin\_debug\_query\_value\_path(jsquery) – for jsonb\_value\_path\_ops + +Result of these functions is a textual representation of query tree which +leafs are GIN search entries. Following examples show different results of +query optimization by different opclasses. + + # SELECT gin_debug_query_path_value('x = 1 AND (*.y = 1 OR y = 2)'); + gin_debug_query_path_value + ---------------------------- + x = 1 , entry 0 + + + # SELECT gin_debug_query_value_path('x = 1 AND (*.y = 1 OR y = 2)'); + gin_debug_query_value_path + ---------------------------- + AND + + x = 1 , entry 0 + + OR + + *.y = 1 , entry 1 + + y = 2 , entry 2 + + +Unfortunately, jsonb have no statistics yet. That's why JsQuery optimizer has +to do imperative decision while selecting conditions to be evaluated using +index. This decision is made by assumtion that some condition types are less +selective than others. Optimizer divides conditions into following selectivity +class (listed by descending of selectivity). + + 1. Equality (x = c) + 2. Range (c1 < x < c2) + 3. Inequality (x > c) + 4. Is (x is type) + 5. Any (x = \*) + +Optimizer evades index evaluation of less selective conditions when possible. +For example, in the `x = 1 AND y > 0` query `x = 1` is assumed to be more +selective than `y > 0`. That's why index isn't used for evaluation of `y > 0`. + + # SELECT gin_debug_query_path_value('x = 1 AND y > 0'); + gin_debug_query_path_value + ---------------------------- + x = 1 , entry 0 + + +With lack of statistics decisions made by optimizer can be inaccurate. That's +why JsQuery supports hints. Comments `/*-- index */` and `/*-- noindex */` +placed in the conditions forces optimizer to use and not use index +correspondingly. + + SELECT gin_debug_query_path_value('x = 1 AND y /*-- index */ > 0'); + gin_debug_query_path_value + ---------------------------- + AND + + x = 1 , entry 0 + + y > 0 , entry 1 + + + SELECT gin_debug_query_path_value('x /*-- noindex */ = 1 AND y > 0'); + gin_debug_query_path_value + ---------------------------- + y > 0 , entry 0 + + +Contribution +------------ + +Please, notice, that JsQuery is still under development and while it's +stable and tested, it may contains some bugs. Don't hesitate to raise +[issues at github](https://github.com/postgrespro/jsquery/issues) with your +bug reports. + +If you're lacking of some functionality in JsQuery and feeling power to +implement it then you're welcome to make pull requests. + diff --git a/jsquery/data/test_jsquery.data b/jsquery/data/test_jsquery.data new file mode 100644 index 0000000000..01d86607c2 --- /dev/null +++ b/jsquery/data/test_jsquery.data @@ -0,0 +1,1034 @@ +{"product_id": "0739301985", "customer_id": "A38QYR68FTYMLF", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Skipping Christmas", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 350857, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440242002", "0385510438", "044023722X", "0440241537", "0440225701"], "review_helpful_votes": 0} +{"product_id": "1579902022", "customer_id": "A38RB1X3RP1KVS", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Ceramic Glaze Handbook", "review_rating": 2, "product_category": "Home & Garden", "product_sales_rank": 502565, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": ["0873418212", "0873418638", "0823005941", "0873493591", "0812217829"], "review_helpful_votes": 3} +{"product_id": "0140043128", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 34067, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "0140236015", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 180313, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "014028334X", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest (Penguin Great Books of the 20th Century)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 504816, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "0142000744", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1460803, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0451163966", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 758, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "0453008151", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest Cassette ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 657021, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "0670030589", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 363845, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "088103715X", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 491328, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} +{"product_id": "097143400X", "customer_id": "A38YMVFX82QNNY", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Spades for Winners", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 560023, "product_subcategory": "Games", "similar_product_ids": ["0971434018", "1566251451", "0970631219", "1566251478", "0486236307"], "review_helpful_votes": 5} +{"product_id": "0060175281", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 274350, "product_subcategory": "Self-Help", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} +{"product_id": "0060928921", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 32519, "product_subcategory": "Self-Help", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} +{"product_id": "0061094943", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 7644, "product_subcategory": "New Age", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} +{"product_id": "069451778X", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 163327, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} +{"product_id": "0694525472", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny CD", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 41723, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} +{"product_id": "1561719226", "customer_id": "A3928WDFMAH8T3", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Princess Diana", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 204716, "product_subcategory": "General", "similar_product_ids": ["0595243622", "1843170841", "1843170051", "1932270213", "0740747134"], "review_helpful_votes": 4} +{"product_id": "0671874756", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Mist ", "review_rating": 3, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 235472, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0671046179", "074352005X", "B00005BB4A", "074352585X", "0140869441"], "review_helpful_votes": 6} +{"product_id": "0451188462", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9607, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "0451188462", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9607, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "1568954204", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation (Wheeler Compass)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1087464, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "1568954204", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation (Wheeler Compass)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1087464, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "1880418363", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 876086, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "1880418363", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 876086, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} +{"product_id": "B0000036R8", "customer_id": "A39A7PMGPZLU3C", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Slanted & Enchanted", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 47222, "product_subcategory": "General", "similar_product_ids": ["B00000JH3F", "B000002LRJ", "B000003TAL", "B00003WG0M", "B000003TBP"], "review_helpful_votes": 0} +{"product_id": "B000056PA6", "customer_id": "A39J6P6WZ3123O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Double Album", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 186939, "product_subcategory": "General", "similar_product_ids": ["B00006FWZR", "B0002062SW"], "review_helpful_votes": 0} +{"product_id": "0345350804", "customer_id": "A39LHZVO6GM1UN", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Best of H. P. Lovecraft", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 24893, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345384210", "0345329457", "034542204X", "0345384229", "034545829X"], "review_helpful_votes": 1} +{"product_id": "0399146113", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 1049, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} +{"product_id": "0425179613", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 84, "product_subcategory": "Biographies", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} +{"product_id": "0786229004", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 1011554, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} +{"product_id": "1565114485", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 278461, "product_subcategory": "Biographies & Memoirs", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} +{"product_id": "1565114493", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 18513, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} +{"product_id": "B000059LIO", "customer_id": "A39YV82M0W26J5", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Chase of Gain", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 273222, "product_subcategory": "Alternative Rock", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "0141802820", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 990849, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} +{"product_id": "0141802847", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 686308, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} +{"product_id": "0451204948", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 28695, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} +{"product_id": "0670896764", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 237651, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} +{"product_id": "B00008RWPR", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 118872, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} +{"product_id": "0671008749", "customer_id": "A3A47FWSCY5MF3", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "FEAR HALL THE BEGINNING", "review_rating": 1, "product_category": "Children's Books", "product_sales_rank": 315182, "product_subcategory": "Literature", "similar_product_ids": ["0671008757", "0671002937", "0671894277", "0671529560", "0671894285"], "review_helpful_votes": 0} +{"product_id": "0613191455", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 531619, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0671315285", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "7 Habits Of Highly Effective People Cd", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 4930, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0671663984", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "SEVEN HABITS OF HIGHLY EFFECTIVE PEOPLE ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 24029, "product_subcategory": "Self-Help", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0671687964", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 20933, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0671708635", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 405, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0762408332", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People, Miniature Edition", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 62430, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "1883219027", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 105050, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "188321923X", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 797624, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "1883219337", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 491926, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "B00005NBPJ", "customer_id": "A3SWZXMFQ6HH2Y", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Salinas Sessions", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 216727, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "188321937X", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 3961, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "1883219973", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 137836, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "1929494157", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 584125, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "9992006684", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People/Cassettes", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 274919, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} +{"product_id": "0515132292", "customer_id": "A3AAWL56G1X1Y8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Wild", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 21008, "product_subcategory": "General", "similar_product_ids": ["082177512X", "0758203381", "0758200846", "0758200862", "0758203403"], "review_helpful_votes": 0} +{"product_id": "0061066206", "customer_id": "A3GE8S9SWTIBLF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Britney Spears", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 955464, "product_subcategory": "Arts & Literature", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B00005Y6YJ", "customer_id": "A3AD9XYOEDT5RG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Oz - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 1046, "product_subcategory": "General", "similar_product_ids": ["B00000FBH2", "B0000Y40PW", "B00031TYBC", "B0009GV9E6", "B0002ERXC2"], "review_helpful_votes": 2} +{"product_id": "B00005Y74V", "customer_id": "A3AD9XYOEDT5RG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Oz - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 18526, "product_subcategory": "General", "similar_product_ids": ["B00000FBH2", "B0000Y40PW", "B00031TYBC", "B0009GV9E6", "B0002ERXC2"], "review_helpful_votes": 2} +{"product_id": "0553487639", "customer_id": "A3AHF0928XXGDI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Rewind (Replica", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 607635, "product_subcategory": "Literature", "similar_product_ids": ["0553487655", "0553487663", "0553487671", "055348768X", "0553487477"], "review_helpful_votes": 1} +{"product_id": "1573226068", "customer_id": "A3AIXV6S91MXA5", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Drown", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 18817, "product_subcategory": "General", "similar_product_ids": ["0345381432", "0679781420", "0375705899", "0452268060", "0743212029"], "review_helpful_votes": 0} +{"product_id": "0684823454", "customer_id": "A3AKSXRPSMNBD7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "My Early Life", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 48686, "product_subcategory": "General", "similar_product_ids": ["0060925779", "0226106330", "1592249930", "1401300561", "0395599687"], "review_helpful_votes": 3} +{"product_id": "051513225X", "customer_id": "A3AO3E9HYX8EQK", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Pendragon", "review_rating": 3, "product_category": "Romance", "product_sales_rank": 75503, "product_subcategory": "General", "similar_product_ids": ["0515127213", "0515129933", "0515124206", "0515111317", "0515109746"], "review_helpful_votes": 19} +{"product_id": "0439112095", "customer_id": "A3APYWXL54R4R6", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Westward to Home", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 296984, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0439389003", "0439370582", "0439369088", "043936907X", "0140383190"], "review_helpful_votes": 6} +{"product_id": "B0000009S9", "customer_id": "A3ARS50BR4K4CF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Fillmore East - June 1971", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 13506, "product_subcategory": "Progressive", "similar_product_ids": ["B0000009SD", "B0000009SK", "B0000009S5", "B0000009S8", "B0000009SS"], "review_helpful_votes": 1} +{"product_id": "B00005RGKA", "customer_id": "A3AV5ERQ22MUEL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Five Iron Frenzy 2", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 21737, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV"], "review_helpful_votes": 0} +{"product_id": "B000002H33", "customer_id": "A3AVZYA1FP3V91", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Master of Puppets", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 1179, "product_subcategory": "General", "similar_product_ids": ["B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"], "review_helpful_votes": 0} +{"product_id": "B000002H34", "customer_id": "A3AVZYA1FP3V91", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Master of Puppets", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 206419, "product_subcategory": "General", "similar_product_ids": ["B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"], "review_helpful_votes": 0} +{"product_id": "0312077866", "customer_id": "A3AYHE64D8B2SP", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Radio Waves", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 529294, "product_subcategory": "Radio", "similar_product_ids": ["0879306645", "0812992652", "0814793827"], "review_helpful_votes": 1} +{"product_id": "0789475006", "customer_id": "A3AZAJ7W69IE9G", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Fairways", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 319971, "product_subcategory": "Golf", "similar_product_ids": ["0810949504", "0810941341", "0810933721", "0762722223", "1579651623"], "review_helpful_votes": 3} +{"product_id": "0934837163", "customer_id": "A3AZV6OXKSDKAD", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Silent Scream", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 24165, "product_subcategory": "Instructional", "similar_product_ids": ["1573411205", "0934837120", "B00028HBKM"], "review_helpful_votes": 7} +{"product_id": "0138947597", "customer_id": "A3B0DQ7XUNU5PU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Intranet Security", "review_rating": 1, "product_category": "Computers & Internet", "product_sales_rank": 723293, "product_subcategory": "Digital Business & Culture", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "B000002ADT", "customer_id": "A3BA8EGMN2G5W3", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Kind of Blue", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 117, "product_subcategory": "General", "similar_product_ids": ["B000002AGN", "B0000A118M", "B000000Y2F", "B00005614M", "B000005H7D"], "review_helpful_votes": 5} +{"product_id": "B00003XAQ5", "customer_id": "A3BA8EGMN2G5W3", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Kind Of Blue", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 14330, "product_subcategory": "General", "similar_product_ids": ["B000002AGN", "B0000A118M", "B000000Y2F", "B00005614M", "B000005H7D"], "review_helpful_votes": 5} +{"product_id": "0826210155", "customer_id": "A3BB7DN7TMPR8Q", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Ghost in the Little House", "review_rating": 1, "product_category": "Biographies & Memoirs", "product_sales_rank": 463834, "product_subcategory": "Arts & Literature", "similar_product_ids": ["0803279140", "0826211674", "0803279175", "0064406989", "0060278420"], "review_helpful_votes": 4} +{"product_id": "B00000I0PF", "customer_id": "A3BFJFJRXMWXAX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "When Pus Comes to Shove", "review_rating": 3, "product_category": "Rock", "product_sales_rank": 65105, "product_subcategory": "General", "similar_product_ids": ["B00004R8QG", "B00005T61I", "B0002VE1U2", "B00067HPCS", "B000068C7W"], "review_helpful_votes": 1} +{"product_id": "B00000JYPW", "customer_id": "A3BFJFJRXMWXAX", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Liberate Te Ex Inferis", "review_rating": 4, "product_category": "Christian & Gospel", "product_sales_rank": 21147, "product_subcategory": "Christian Rock", "similar_product_ids": ["B000006P3V", "B000059T5U", "B00008BNU5", "B0002IQ9SW", "B000069CKJ"], "review_helpful_votes": 0} +{"product_id": "B00004T99Z", "customer_id": "A3BJO1U7IZHDN7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Mer de Noms", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 1973, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0000AZJXQ", "B000641ZIQ", "B00005B36H", "B00000099Y", "B000000993"], "review_helpful_votes": 1} +{"product_id": "B00004T9RX", "customer_id": "A3BJO1U7IZHDN7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Mer de Noms", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 359411, "product_subcategory": "Alternative Styles", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "1561583774", "customer_id": "A3BO9UEYQ2NYWE", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Creating the Not So Big House", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 31279, "product_subcategory": "Home Design", "similar_product_ids": ["1561583766", "1561586137", "1561586188", "1561582298", "1561585335"], "review_helpful_votes": 15} +{"product_id": "1561586056", "customer_id": "A3BO9UEYQ2NYWE", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Creating the Not So Big House", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 24446, "product_subcategory": "Home Design", "similar_product_ids": ["1561583766", "1561586137", "1561586188", "1561582298", "1561585335"], "review_helpful_votes": 15} +{"product_id": "0843947462", "customer_id": "A3BPPDT8CEY5G7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The House That Jack Built", "review_rating": 3, "product_category": "Horror", "product_sales_rank": 288279, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["084394935X", "0843946334", "0843952407", "0812522028", "0812545338"], "review_helpful_votes": 0} +{"product_id": "0375421041", "customer_id": "A3C5O0WY6LLENW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Dark Room ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 476024, "product_subcategory": "World Literature", "similar_product_ids": ["0156027402", "0385722109", "038572179X", "0140286233", "0375507256"], "review_helpful_votes": 7} +{"product_id": "0375726322", "customer_id": "A3C5O0WY6LLENW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Dark Room ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 389993, "product_subcategory": "General", "similar_product_ids": ["0156027402", "0140286233", "0385722109", "038572179X", "0375507256"], "review_helpful_votes": 7} +{"product_id": "B00005JKVZ", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 9181, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} +{"product_id": "B00005JKW0", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1321, "product_subcategory": "General", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} +{"product_id": "B000067JH8", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 56341, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} +{"product_id": "B00005QDVS", "customer_id": "A3C9I2XZ8HY0U6", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "This Way", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 7039, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00000F1CY", "B000002J2S", "B00008OWZE", "B00000K53Y", "B000089RVR"], "review_helpful_votes": 0} +{"product_id": "0425181685", "customer_id": "A3CHO24ZFMD1LD", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Narcissus in Chains (An Anita Blake, Vampire Hunter Novel, Book 10)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 134033, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0515136816", "0515134473", "0515134511", "0515134465", "0425198243"], "review_helpful_votes": 3} +{"product_id": "0515133876", "customer_id": "A3CHO24ZFMD1LD", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Narcissus in Chains (Anita Blake Vampire Hunter (Paperback))", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 7509, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0515136816", "0515134473", "0515134511", "0515134465", "0425198243"], "review_helpful_votes": 3} +{"product_id": "B00005YUNM", "customer_id": "A3CKF9RX4ADHG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "Sade - Lovers Live", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 9767, "product_subcategory": "General", "similar_product_ids": ["B000056MMD", "B000056MMC", "B00005Y3ZM", "B00005V9QJ", "B00008HCCF"], "review_helpful_votes": 4} +{"product_id": "B00005YUQS", "customer_id": "A3CKF9RX4ADHG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Video", "product_title": "Sade - Lovers Live", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 34586, "product_subcategory": "General", "similar_product_ids": ["B000056MMD", "B000056MMC", "B00005Y3ZM", "B00008HCCF", "B00005V9QJ"], "review_helpful_votes": 4} +{"product_id": "0312268017", "customer_id": "A3CU3GER3D7K7A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Accidental Pope", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 343027, "product_subcategory": "Christianity", "similar_product_ids": ["0812579224", "0812579216", "0812590554", "0385504535", "0425042588"], "review_helpful_votes": 2} +{"product_id": "0312282982", "customer_id": "A3CU3GER3D7K7A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Accidental Pope ", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 131115, "product_subcategory": "General", "similar_product_ids": ["0812579224", "0812579216", "0812590554", "0385504535", "1902881842"], "review_helpful_votes": 2} +{"product_id": "0385315279", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 7359, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} +{"product_id": "0553528610", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 406433, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} +{"product_id": "0553714473", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 201281, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} +{"product_id": "6303929478", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Muppet Sing Alongs - Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 21639, "product_subcategory": "Animation", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} +{"product_id": "6304089627", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4919, "product_subcategory": "Comedy", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} +{"product_id": "B00006472V", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 1203, "product_subcategory": "Characters & Series", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} +{"product_id": "6300215555", "customer_id": "A3D33WFGYFW6DG", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "We're No Angels", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 162, "product_subcategory": "By Year", "similar_product_ids": ["630150528X", "079074886X", "B00003XAMY", "0790748789", "B00003XAMX"], "review_helpful_votes": 4} +{"product_id": "0062517821", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 97490, "product_subcategory": "Self-Help", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0062516965", "0743537246"], "review_helpful_votes": 17} +{"product_id": "006251783X", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 25513, "product_subcategory": "Self-Help", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0062516965", "0743537246"], "review_helpful_votes": 17} +{"product_id": "0694526606", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 444066, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0743537246", "0062516965"], "review_helpful_votes": 17} +{"product_id": "B00005JKVZ", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 9181, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} +{"product_id": "B00005JKW0", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1321, "product_subcategory": "General", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} +{"product_id": "B000067JH8", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 56341, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} +{"product_id": "6304935803", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton (Widescreen Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 30855, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} +{"product_id": "6304935811", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton", "review_rating": 5, "product_category": "Military & War", "product_sales_rank": 16952, "product_subcategory": "Action & Combat", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} +{"product_id": "6305622930", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Patton", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 23484, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} +{"product_id": "B00005PJ8O", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Patton", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 915, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} +{"product_id": "B00005Q4GV", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton", "review_rating": 5, "product_category": "Military & War", "product_sales_rank": 291, "product_subcategory": "World War II", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} +{"product_id": "0195116313", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Making Sense of the Molly Maguires", "review_rating": 5, "product_category": "History", "product_sales_rank": 48270, "product_subcategory": "Americas", "similar_product_ids": ["B0001FGBLG", "0681828757", "0395979145", "1572493194", "0801828724"], "review_helpful_votes": 2} +{"product_id": "0312169922", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Rune Cards", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 286086, "product_subcategory": "New Age", "similar_product_ids": ["0312097581", "0312135076", "0875425933", "0877285489", "1592230423"], "review_helpful_votes": 2} +{"product_id": "0345339703", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 42596, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0345339703", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 42596, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0395489318", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 162177, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0395489318", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 162177, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0553714775", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (BBC Full Cast Dramatization)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 986248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0553714775", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (BBC Full Cast Dramatization)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 986248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618002227", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 77882, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618002227", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 77882, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618129030", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 365264, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618129030", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 365264, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618153985", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 813447, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618153985", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 813447, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618260269", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 956259, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0618260269", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 956259, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "061826051X", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 218871, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "061826051X", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 218871, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0788789538", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106027, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0788789538", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106027, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0788789813", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 17171, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0788789813", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 17171, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0808520768", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (Lord of the Rings (Paperback))", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 862897, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "0808520768", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (Lord of the Rings (Paperback))", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 862897, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "1556903219", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 2256332, "product_subcategory": "Children's Books", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "1556903219", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 2256332, "product_subcategory": "Children's Books", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "1565116674", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Books on CD", "product_sales_rank": 707553, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "1565116674", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Books on CD", "product_sales_rank": 707553, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} +{"product_id": "B00000I1PT", "customer_id": "A3DIG2DP9536FN", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Gilad Step Aerobics - On the Beach at Waikiki", "review_rating": 5, "product_category": "Fitness", "product_sales_rank": 11000, "product_subcategory": "General", "similar_product_ids": ["6302967945", "6303182364", "1573309931", "6302872162", "1573309966"], "review_helpful_votes": 3} +{"product_id": "0316606103", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Cirque Du Freak #2", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 112022, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} +{"product_id": "0316606847", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Vampire's Assistant (Cirque du Freak, Book 2)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 81251, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} +{"product_id": "0786237341", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Cirque Du Freak", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1481041, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} +{"product_id": "B00005RKTS", "customer_id": "A3DMTE8US4ARIJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Interzone Mantras", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 16795, "product_subcategory": "Goth & Industrial", "similar_product_ids": ["B0002Q9WEM", "B00000JOQ3", "B000003JE3", "B000003JD0", "B00002ZZH9"], "review_helpful_votes": 1} +{"product_id": "B00005A8OB", "customer_id": "A3DQ0INH14A1N6", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Lars Frederiksen & The Bastards", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 7215, "product_subcategory": "General", "similar_product_ids": ["B00027JYV2", "B00004W52U", "B00006JTGU", "B000001IQH", "B000001IPP"], "review_helpful_votes": 0} +{"product_id": "B00004XQW4", "customer_id": "A3DQ0INH14A1N6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Let Me Go E.P.", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 209804, "product_subcategory": "General", "similar_product_ids": ["B00027JYV2", "B000001IR1", "B00004UEHL", "B000007OED", "B000001IPP"], "review_helpful_votes": 0} +{"product_id": "0028612744", "customer_id": "A3DQHHCPK03MO6", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Complete Idiot's Guide to Buying or Leasing a Car (The Complete Idiot's Guide)", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 752789, "product_subcategory": "General", "similar_product_ids": ["0028625242", "0141001496", "0764550918", "0890439850", "0877596905"], "review_helpful_votes": 3} +{"product_id": "0553712853", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 340794, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} +{"product_id": "060960922X", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 152704, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} +{"product_id": "1400046831", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 6296, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} +{"product_id": "0780020405", "customer_id": "A3E2UT8NVCLMLH", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "The Night Porter", "review_rating": 3, "product_category": "Cult Movies", "product_sales_rank": 17568, "product_subcategory": "Drama", "similar_product_ids": ["B0000WN10O", "B00005JKGO", "B0000WN118", "B00005JMIJ", "B0000WN0ZK"], "review_helpful_votes": 4} +{"product_id": "0780022823", "customer_id": "A3E2UT8NVCLMLH", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "The Night Porter - Criterion Collection", "review_rating": 3, "product_category": "Art House & International", "product_sales_rank": 7920, "product_subcategory": "By Genre", "similar_product_ids": ["B0000WN10O", "B00005JKGO", "B00005JMIJ", "B0000WN118", "B00023P4I8"], "review_helpful_votes": 4} +{"product_id": "0967143934", "customer_id": "A3E9PWC2B1EHDB", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Marketing to American Latinos", "review_rating": 3, "product_category": "Business & Investing", "product_sales_rank": 573031, "product_subcategory": "General", "similar_product_ids": ["0595287298", "0765612917", "0520227247", "0534241921", "0972529055"], "review_helpful_votes": 1} +{"product_id": "0967143977", "customer_id": "A3E9PWC2B1EHDB", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Marketing to American Latinos", "review_rating": 3, "product_category": "Business & Investing", "product_sales_rank": 674865, "product_subcategory": "General", "similar_product_ids": ["0595287298", "0765612917", "0520227247", "0534241921", "0972529055"], "review_helpful_votes": 1} +{"product_id": "0609600575", "customer_id": "A3EDG6KTCARNUU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Dogs Never Lie About Love ", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 94346, "product_subcategory": "Animal Care & Pets", "similar_product_ids": ["0385314280", "0345448820", "034545281X", "0761518088", "0385317018"], "review_helpful_votes": 9} +{"product_id": "0609802011", "customer_id": "A3EDG6KTCARNUU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Dogs Never Lie About Love ", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 156867, "product_subcategory": "Animal Care & Pets", "similar_product_ids": ["0385314280", "0345448820", "034545281X", "0761518088", "0385317018"], "review_helpful_votes": 9} +{"product_id": "B00003CWQI", "customer_id": "A3EEGR2D3SJJ3N", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Fritz the Cat", "review_rating": 4, "product_category": "Animation", "product_sales_rank": 4055, "product_subcategory": "General", "similar_product_ids": ["B00005PJ6S", "0792846818", "B0001NBMIK", "0767836316", "6305641587"], "review_helpful_votes": 0} +{"product_id": "055358376X", "customer_id": "A3EF0QEZLMHT0R", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Maximum Ice", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 453656, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0553583794", "055358023X", "0553580264", "055357681X", "0812579844"], "review_helpful_votes": 3} +{"product_id": "B00005R09Z", "customer_id": "A3EJYJC25OJVKK", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Cure - Greatest Hits", "review_rating": 2, "product_category": "Alternative Rock", "product_sales_rank": 330, "product_subcategory": "General", "similar_product_ids": ["B000002MVM", "B00000DAGD", "B000002H70", "B000002MZ4", "B00000DG1R"], "review_helpful_votes": 1} +{"product_id": "B00005O0ST", "customer_id": "A3ETFYXFZ6WYX8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Anne of Green Gables - The Continuing Story", "review_rating": 1, "product_category": "Kids & Family", "product_sales_rank": 402, "product_subcategory": "General", "similar_product_ids": ["B00005YNTR", "0553609416", "B00019PDWK", "B00005NGVV", "B0000C2IUY"], "review_helpful_votes": 6} +{"product_id": "1892065037", "customer_id": "A3EU3AOJA5C33T", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "I Dare (Liaden Universe Novel Series)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 270579, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["1892065029", "0441010229", "0441009913", "0441009646", "0441009271"], "review_helpful_votes": 0} +{"product_id": "1892065126", "customer_id": "A3EU3AOJA5C33T", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "I Dare (Liaden Universe Novel Series)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1186248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0441010229", "1892065029", "0441009913", "0441009646", "0441009271"], "review_helpful_votes": 0} +{"product_id": "6304744404", "customer_id": "A3EVZ97UPAZKY9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Event Horizon", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 26422, "product_subcategory": "General", "similar_product_ids": ["079073639X", "078062856X", "B00005JMZK", "0780622553", "B0002CHK1S"], "review_helpful_votes": 0} +{"product_id": "6305222916", "customer_id": "A3EVZ97UPAZKY9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Event Horizon", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2456, "product_subcategory": "General", "similar_product_ids": ["079073639X", "078062856X", "B00005JMZK", "0780622553", "B0002CHK1S"], "review_helpful_votes": 0} +{"product_id": "1589894006", "customer_id": "A3F83O1T8Q719Z", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Legend of Rah and the Muggles", "review_rating": 1, "product_category": "", "product_sales_rank": 657028, "product_subcategory": "", "similar_product_ids": [], "review_helpful_votes": 5} +{"product_id": "0446601543", "customer_id": "A3F92NHH9VOJKB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Deadly Innocence", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 7012, "product_subcategory": "True Accounts", "similar_product_ids": ["055356854X", "0345465806", "2895940002", "0440204429", "0786015179"], "review_helpful_votes": 0} +{"product_id": "B00004WG90", "customer_id": "A3FAX9MR67HYOA", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "French & Saunders", "review_rating": 4, "product_category": "Television", "product_sales_rank": 35489, "product_subcategory": "General", "similar_product_ids": ["B00005U2KK", "B00005U2KL", "B0000A02YF", "B0006Z2KZW", "B0006Z2KZM"], "review_helpful_votes": 3} +{"product_id": "B00005UERL", "customer_id": "A3FAX9MR67HYOA", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "French & Saunders", "review_rating": 4, "product_category": "Comedy", "product_sales_rank": 23340, "product_subcategory": "General", "similar_product_ids": ["B00005U2KK", "B00005U2KL", "B0000A02YF", "B0006Z2KZW", "B0006Z2KZM"], "review_helpful_votes": 3} +{"product_id": "0743237188", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall On Your Knees (Oprah #45)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 5896, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} +{"product_id": "0743237196", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 519477, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} +{"product_id": "0743466527", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees (Oprah's Book Club)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 51277, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} +{"product_id": "1565116917", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees cass (Oprah's Book Club (St. Paul, Minn.).)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 170216, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} +{"product_id": "1565116925", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 639401, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} +{"product_id": "B00005899O", "customer_id": "A3FFKTKYGDG3HP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Tantric", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 5543, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0001977K6", "B000002RBX", "B00005O6K6", "B00000JWLU", "B0002A2VS2"], "review_helpful_votes": 0} +{"product_id": "B00005QZ7U", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Moulin Rouge (Double Digipack)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 1425, "product_subcategory": "General", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} +{"product_id": "B00005YTFG", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Moulin Rouge (Special Edition)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 4748, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} +{"product_id": "B000062XLM", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Moulin Rouge", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 48083, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} +{"product_id": "B000077VR3", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Moulin Rouge (Single Disc Edition)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 4836, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} +{"product_id": "0060608145", "customer_id": "A3FM0PAT23VTNA", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Jesus", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 28277, "product_subcategory": "Christianity", "similar_product_ids": ["0060609176", "0060526769", "0060610352", "0060609192", "0060608765"], "review_helpful_votes": 6} +{"product_id": "6305500908", "customer_id": "A3FMVF6W9D3TSB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Sonic the Hedgehog", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 10499, "product_subcategory": "Animation", "similar_product_ids": ["B0000AZT6G", "B00011ZBEI", "B0001MZ7BY", "B0001MZ7B4", "1879794047"], "review_helpful_votes": 0} +{"product_id": "B00000JGOK", "customer_id": "A3FMVF6W9D3TSB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Sonic The Hedgehog - The Movie", "review_rating": 4, "product_category": "Anime & Manga", "product_sales_rank": 35235, "product_subcategory": "By Studio", "similar_product_ids": ["B0000AZT6G", "B00011ZBEI", "B0001MZ7BY", "B0001MZ7B4", "1879794047"], "review_helpful_votes": 0} +{"product_id": "0375431489", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} +{"product_id": "0385503822", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} +{"product_id": "0440241073", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} +{"product_id": "0553528912", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} +{"product_id": "0553714635", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} +{"product_id": "B00005Y1NF", "customer_id": "A3FVO92GDDCYJW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "Star Trek The Next Generation - The Complete First Season", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 6137, "product_subcategory": "General", "similar_product_ids": ["B000062XFG", "B000063V8R", "B000063V8S", "B000063V8T", "B000063V8V"], "review_helpful_votes": 2} +{"product_id": "1893756084", "customer_id": "A3FZ3STI2X5RIM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "The Best", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 193689, "product_subcategory": "Investing", "similar_product_ids": ["0471710490", "0131446037", "0071437886", "140006337X", "0887309569"], "review_helpful_votes": 5} +{"product_id": "0967446805", "customer_id": "A3FZMHPQYQSE7D", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "123 A Family Counting Book", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 146113, "product_subcategory": "Baby-3", "similar_product_ids": ["0316738964", "188367266X", "1555835430", "1884834698", "1413416004"], "review_helpful_votes": 7} +{"product_id": "0446678546", "customer_id": "A3G31NPX7YU7TT", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "The Hell with Love ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 101327, "product_subcategory": "Poetry", "similar_product_ids": ["0446690287", "068480302X", "0786884274", "0767909089", "0609807927"], "review_helpful_votes": 8} +{"product_id": "B00005NZDW", "customer_id": "A3G3D68D9GTVFD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Songs from the West Coast", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 12899, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00061X95Q", "B000001EXB", "B0000089F2", "B000009EJU", "B000001EG4"], "review_helpful_votes": 3} +{"product_id": "B00000JMOI", "customer_id": "A3G3DXHBPXYDS4", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Video", "product_title": "Open Your Eyes", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 2039, "product_subcategory": "By Country", "similar_product_ids": ["B00005N8A9", "B00005JKMZ", "B00005JL57", "B00005JLQW", "1928639011"], "review_helpful_votes": 5} +{"product_id": "B00005LZOD", "customer_id": "A3G3DXHBPXYDS4", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "DVD", "product_title": "Open Your Eyes", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 5428, "product_subcategory": "By Genre", "similar_product_ids": ["B00005N8A9", "B00005JKMZ", "B00005JL57", "B00005JLQW", "1928639011"], "review_helpful_votes": 5} +{"product_id": "B0000062XK", "customer_id": "A3G81594MU0PM8", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Music", "product_title": "Odds & Sods", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 33229, "product_subcategory": "British Invasion", "similar_product_ids": ["B000002P2W", "B000002P2V", "B000002OX5", "B00000761Z", "B000002OX3"], "review_helpful_votes": 10} +{"product_id": "0205309151", "customer_id": "A3GB9OUJ1SI975", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Technology for Teaching", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 104804, "product_subcategory": "Education", "similar_product_ids": ["0761975659", "1557987912", "0534603092", "0807735868", "0130484032"], "review_helpful_votes": 1} +{"product_id": "B000001Y57", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Sailing the Seas of Cheese", "review_rating": 3, "product_category": "Alternative Rock", "product_sales_rank": 6082, "product_subcategory": "General", "similar_product_ids": ["B000001Y5P", "B0000645KT", "B000001Y73", "B000028TV7", "B000001Y47"], "review_helpful_votes": 0} +{"product_id": "B000028TV7", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Antipop", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 10197, "product_subcategory": "General", "similar_product_ids": ["B000001Y47", "B000001Y73", "B000001Y57", "B000001Y5P", "B0000645KT"], "review_helpful_votes": 0} +{"product_id": "0794807135", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 49, "product_group": "Book", "product_title": "The Official U.S. Mint 50 State Quarters", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 15094, "product_subcategory": "Antiques & Collectibles", "similar_product_ids": ["1582380783", "0794807607", "158238097X", "0307090302", "1582380953"], "review_helpful_votes": 49} +{"product_id": "1573305715", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Sesame Street - The Alphabet Jungle Game", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 6512, "product_subcategory": "Educational", "similar_product_ids": ["0738920762", "B00005QFDV", "0738920770", "630227608X", "B000065U1L"], "review_helpful_votes": 0} +{"product_id": "B00005QFDW", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Sesame Street - The Alphabet Jungle Game", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 5774, "product_subcategory": "General", "similar_product_ids": ["0738920762", "B00005QFDV", "0738920770", "630227608X", "B000065U1L"], "review_helpful_votes": 0} +{"product_id": "6304279507", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Sesame Street - Telling the Truth", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 15880, "product_subcategory": "Educational", "similar_product_ids": ["6303911560", "B00009W0TY", "B00008QSAF", "0738920762", "B000065U1L"], "review_helpful_votes": 4} +{"product_id": "B00008QSAH", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Sesame Street - Telling the Truth", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 8291, "product_subcategory": "General", "similar_product_ids": ["6303911560", "B00009W0TY", "B00008QSAF", "0738920762", "B000065U1L"], "review_helpful_votes": 4} +{"product_id": "6301797973", "customer_id": "A3GDW190U77XN", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "High Anxiety", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 61, "product_subcategory": "General", "similar_product_ids": ["6305168857", "6301798643", "B00000K3CQ", "B0001Z4OXS", "6302946387"], "review_helpful_votes": 0} +{"product_id": "0061066206", "customer_id": "A3GE8S9SWTIBLF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Britney Spears", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 955464, "product_subcategory": "Arts & Literature", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B00005Y1N2", "customer_id": "A3GG9Z4SIMU55E", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Gold", "review_rating": 2, "product_category": "Pop", "product_sales_rank": 9048, "product_subcategory": "General", "similar_product_ids": ["B000002JC4", "B00001QEOL", "B000088E4T", "B0000AM6LZ", "B00004YNGO"], "review_helpful_votes": 3} +{"product_id": "0765341921", "customer_id": "A3GK3C57LBH6WC", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Beyond Ender's Game", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 7715, "product_subcategory": "Science Fiction", "similar_product_ids": ["0765344955", "0765308738", "0312857586", "0812575717", "0765349981"], "review_helpful_votes": 2} +{"product_id": "1569246483", "customer_id": "A3GO7UV9XX14D8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Storyteller's Goddess", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 495907, "product_subcategory": "Social Sciences", "similar_product_ids": ["156924443X", "1569246173", "006250276X", "0062503545", "0892815507"], "review_helpful_votes": 2} +{"product_id": "0375431489", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} +{"product_id": "0385503822", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} +{"product_id": "0440241073", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} +{"product_id": "0553528912", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} +{"product_id": "0553714635", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} +{"product_id": "0767002652", "customer_id": "A3GT2VY34AXBOJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Upstairs Downstairs - The Premiere Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 4869, "product_subcategory": "TV Series", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 7} +{"product_id": "B00005NKCM", "customer_id": "A3GT2VY34AXBOJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Upstairs Downstairs - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 5806, "product_subcategory": "A&E Home Video", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 7} +{"product_id": "0684819066", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 309670, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} +{"product_id": "0684853701", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A BEAUTIFUL MIND", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 37365, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} +{"product_id": "0743224574", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 11065, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} +{"product_id": "0743509889", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 850520, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0486296725", "0688168949"], "review_helpful_votes": 16} +{"product_id": "0743509897", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 296367, "product_subcategory": "Biographies & Memoirs", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} +{"product_id": "078624223X", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind (Thorndike Press Large Print Biography Series)", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 987105, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} +{"product_id": "0140443886", "customer_id": "A3GYHHYQEPEKJM", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Rome and Italy ", "review_rating": 5, "product_category": "History", "product_sales_rank": 50647, "product_subcategory": "Ancient", "similar_product_ids": ["0140443185", "014044145X", "0140448098", "0140443622", "0140440844"], "review_helpful_votes": 8} +{"product_id": "0780023382", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "The Confessions of Robert Crumb", "review_rating": 3, "product_category": "Documentary", "product_sales_rank": 49280, "product_subcategory": "General", "similar_product_ids": ["0767821505", "1840727160", "B00003CWQI", "0867193743", "0930193792"], "review_helpful_votes": 6} +{"product_id": "B00005UQ7P", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "The Confessions of Robert Crumb", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 26273, "product_subcategory": "Art & Artists", "similar_product_ids": ["0767821505", "1840727160", "B00003CWQI", "0867193743", "0930193792"], "review_helpful_votes": 6} +{"product_id": "078881172X", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 279, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} +{"product_id": "B00001QEE5", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Peter Pan (Limited Issue)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 2457, "product_subcategory": "Animation", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} +{"product_id": "B00005RDSM", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Peter Pan (Special Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 2878, "product_subcategory": "Animation", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} +{"product_id": "B00005RDVW", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan (Special Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 4549, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} +{"product_id": "B00005RDWH", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 42438, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} +{"product_id": "0780023390", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Jackson Pollock - Love and Death on Long Island", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 26636, "product_subcategory": "Art & Artists", "similar_product_ids": ["B00005KHJJ", "B000055XMV", "B00005B6KO", "B000055XNK", "B00007ELEI"], "review_helpful_votes": 5} +{"product_id": "B00005UQ7S", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "Jackson Pollock - Love & Death on Long Island", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 23399, "product_subcategory": "Art & Artists", "similar_product_ids": ["B00005KHJJ", "B000055XMV", "B00005B6KO", "B000055XNK", "B00007ELEI"], "review_helpful_votes": 5} +{"product_id": "B000059HE4", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Me & Isaac Newton", "review_rating": 4, "product_category": "Documentary", "product_sales_rank": 45693, "product_subcategory": "General", "similar_product_ids": ["B00006673N", "1565019822", "B00005B327", "B0000ZG0TA", "B0000B1OFS"], "review_helpful_votes": 6} +{"product_id": "B00005T30J", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Me & Isaac Newton", "review_rating": 4, "product_category": "Documentary", "product_sales_rank": 32387, "product_subcategory": "General", "similar_product_ids": ["B00006673N", "1565019822", "B00005B327", "B0000ZG0TA", "B0000B1OFS"], "review_helpful_votes": 6} +{"product_id": "0471293520", "customer_id": "A3HE4NA272OIAH", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Management Consulting", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 516152, "product_subcategory": "General", "similar_product_ids": ["0070534489", "0970431708", "1581312563", "1581311672", "1578511917"], "review_helpful_votes": 5} +{"product_id": "0471444014", "customer_id": "A3HE4NA272OIAH", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Management Consulting", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 214355, "product_subcategory": "General", "similar_product_ids": ["0070534489", "0970431708", "1581312563", "1581311672", "1578511917"], "review_helpful_votes": 5} +{"product_id": "0684841215", "customer_id": "A3HEOREMM29XWV", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "SOMETHING HAPPENED", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 58644, "product_subcategory": "General", "similar_product_ids": ["0374522928", "0684841258", "0684804506", "0684839741", "0684833395"], "review_helpful_votes": 11} +{"product_id": "0781808073", "customer_id": "A3HFAR4RJ7Y0ME", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Afghan Food & Cookery", "review_rating": 5, "product_category": "Cooking, Food & Wine", "product_sales_rank": 17091, "product_subcategory": "General", "similar_product_ids": ["1403385904", "0781806690", "0936347775", "093421154X", "0781809711"], "review_helpful_votes": 6} +{"product_id": "0689815298", "customer_id": "A3HGWA477T9047", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Silverwing", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 786630, "product_subcategory": "Animals", "similar_product_ids": ["0689832877", "0689869886", "0060531800", "0060000023", "0060000074"], "review_helpful_votes": 2} +{"product_id": "0689825587", "customer_id": "A3HGWA477T9047", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "SILVERWING", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 34287, "product_subcategory": "Animals", "similar_product_ids": ["0689832877", "0689869886", "0060531800", "0060000023", "0060000074"], "review_helpful_votes": 2} +{"product_id": "B00005J78F", "customer_id": "A3HH1BDXTWK1LI", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Drums of Fu Manchu", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 37614, "product_subcategory": "Crime", "similar_product_ids": ["B0000JD28S", "B000051SH3", "B000051S39", "B000087F3E", "B000087F1H"], "review_helpful_votes": 6} +{"product_id": "B000087F3F", "customer_id": "A3HH1BDXTWK1LI", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Drums of Fu Manchu", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 21616, "product_subcategory": "Crime", "similar_product_ids": ["B0000JD28S", "B000051SH3", "B000051S39", "B000087F3E", "B000087F1H"], "review_helpful_votes": 6} +{"product_id": "0875886175", "customer_id": "A3HKSYKCEEDREW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In Search of Teddy", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 829034, "product_subcategory": "Antiques & Collectibles", "similar_product_ids": [], "review_helpful_votes": 4} +{"product_id": "1560151234", "customer_id": "A3HMQJOCPLQVLM", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Spanish", "review_rating": 1, "product_category": "Reference", "product_sales_rank": 626333, "product_subcategory": "Foreign Languages", "similar_product_ids": ["1591252040", "159125423X", "159125227X", "1591500427", "0970682913"], "review_helpful_votes": 9} +{"product_id": "B00005M987", "customer_id": "A3HOEJL7PAR5KC", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "The Spirit Room", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 2295, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00009LI14", "B0000646TK", "B000066NW0", "B0001UL7RY", "B0002ZYEKA"], "review_helpful_votes": 0} +{"product_id": "0394806220", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo! Can You? (Bright and Early Books for Beginning Beginners)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 32414, "product_subcategory": "Literature", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} +{"product_id": "0679882820", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo, Can You ", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 722, "product_subcategory": "Baby-3", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} +{"product_id": "0881034126", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo! Can You? (Bright & Early Book)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1402462, "product_subcategory": "Literature", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} +{"product_id": "6305772649", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Classic Albums - Steely Dan", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 7228, "product_subcategory": "General", "similar_product_ids": ["6305846464", "B00004REQZ", "B0000AOV85", "6305320616", "B00005Q2Z4"], "review_helpful_votes": 0} +{"product_id": "B00005A46T", "customer_id": "A3HR0V43CV3WC1", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 1154, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B00000JCOV", "B0001NBMBC", "B00004WK3A", "B0000787EO", "B00007BHOE"], "review_helpful_votes": 0} +{"product_id": "B00005NNNG", "customer_id": "A3HR0V43CV3WC1", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 430847, "product_subcategory": "Alternative Metal", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0764554093", "customer_id": "A3HYF1XWSZ3GN8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Investment Clubs for Dummies", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 16457, "product_subcategory": "General", "similar_product_ids": ["1892547007", "0812930088", "0446671479", "0471392278", "0471369381"], "review_helpful_votes": 6} +{"product_id": "B0000039PW", "customer_id": "A3HYWS34OY5G3R", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Ready to Die", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 2798, "product_subcategory": "East Coast", "similar_product_ids": ["B0000039QA", "B00002S5DF", "B00005AQEQ", "B0000029GA", "B00000FCBH"], "review_helpful_votes": 0} +{"product_id": "B000000XEF", "customer_id": "A3I2VA6S94AB2G", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "The Fugs First Album", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 47285, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B000000XEG", "B00009WVSP", "B000066AUL", "B0000009RT", "B00000K0XX"], "review_helpful_votes": 7} +{"product_id": "0812516826", "customer_id": "A3I92PEEL1B62O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Catnap ", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 242579, "product_subcategory": "Mystery", "similar_product_ids": ["0812516834", "0812534417", "0812544145", "0812555066", "0812530365"], "review_helpful_votes": 2} +{"product_id": "B00005JKJA", "customer_id": "A3I9LMORUC5GAV", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Mulholland Drive", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 1320, "product_subcategory": "Thrillers", "similar_product_ids": ["B000063JDE", "B000060MWU", "B00005JMIJ", "B00005V3Z4", "B000056BP1"], "review_helpful_votes": 3} +{"product_id": "B000060MY6", "customer_id": "A3I9LMORUC5GAV", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Mulholland Dr.", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 14855, "product_subcategory": "Mystery", "similar_product_ids": ["B000063JDE", "B000060MWU", "B00005JMIJ", "B00005V3Z4", "B000056BP1"], "review_helpful_votes": 3} +{"product_id": "1579902022", "customer_id": "A3IAQRJT1T447V", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Ceramic Glaze Handbook", "review_rating": 3, "product_category": "Home & Garden", "product_sales_rank": 502565, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": ["0873418212", "0873418638", "0823005941", "0873493591", "0812217829"], "review_helpful_votes": 7} +{"product_id": "B00005V3WH", "customer_id": "A3ICVJEW6MCP3Z", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Essential Barbra Streisand", "review_rating": 5, "product_category": "Broadway & Vocalists", "product_sales_rank": 4282, "product_subcategory": "Classic Vocalists", "similar_product_ids": ["B00006LFGD", "B0000C1YZI", "B0000025EV", "B0000026W1", "B000002IVS"], "review_helpful_votes": 1} +{"product_id": "0790729709", "customer_id": "A3IK9BLS3BWM96", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Bodyguard (Full Screen Edition)", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 7581, "product_subcategory": "General", "similar_product_ids": ["B000059TEP", "6305696071", "B0002WZTOI", "B000065V3J", "B00005JN0W"], "review_helpful_votes": 1} +{"product_id": "6302779278", "customer_id": "A3IK9BLS3BWM96", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Bodyguard", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 4075, "product_subcategory": "General", "similar_product_ids": ["B000059TEP", "6305696071", "B0002WZTOI", "B000002VMD", "B000065V3J"], "review_helpful_votes": 1} +{"product_id": "B0000071B3", "customer_id": "A3IR0OQESNZO2M", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Eyewitness", "review_rating": 1, "product_category": "Rock", "product_sales_rank": 301460, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0783235798", "customer_id": "A3IYYU0P7CJJ14", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "The Love Letter", "review_rating": 3, "product_category": "Comedy", "product_sales_rank": 14220, "product_subcategory": "General", "similar_product_ids": ["0790739267", "B00006472R", "B0000CNY3G", "B0002S94C0", "B00004Z4ST"], "review_helpful_votes": 0} +{"product_id": "0783239416", "customer_id": "A3IYYU0P7CJJ14", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "The Love Letter", "review_rating": 3, "product_category": "Comedy", "product_sales_rank": 19866, "product_subcategory": "General", "similar_product_ids": ["0790739267", "B00006472R", "B0000CNY3G", "B0002S94C0", "B00004Z4ST"], "review_helpful_votes": 0} +{"product_id": "0521472423", "customer_id": "A3J5JTEB1OPT2Z", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Quantum Field Theory", "review_rating": 3, "product_category": "Science", "product_sales_rank": 1584147, "product_subcategory": "Physics", "similar_product_ids": ["0201503972", "0521831431", "0691010196", "0226870332", "0471941867"], "review_helpful_votes": 4} +{"product_id": "0521478146", "customer_id": "A3J5JTEB1OPT2Z", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Quantum Field Theory", "review_rating": 3, "product_category": "Science", "product_sales_rank": 127991, "product_subcategory": "Physics", "similar_product_ids": ["0201503972", "0521831431", "0691010196", "0226870332", "0471941867"], "review_helpful_votes": 4} +{"product_id": "0399148027", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 328310, "product_subcategory": "General", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} +{"product_id": "0425184943", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 182185, "product_subcategory": "General", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} +{"product_id": "158788254X", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 1070879, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} +{"product_id": "B00004Y2FT", "customer_id": "A3J7LWIOY7DHPZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Stars and Topsoil", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 14505, "product_subcategory": "British Alternative", "similar_product_ids": ["B00006L5PQ", "B00009ATJD", "B00004Y82V", "B00006L5PM", "B00001QEEV"], "review_helpful_votes": 0} +{"product_id": "0375431489", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} +{"product_id": "0385503822", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} +{"product_id": "0440241073", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} +{"product_id": "0553528912", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} +{"product_id": "0553714635", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} +{"product_id": "0767902335", "customer_id": "A3JPYZGUWN0AFS", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Work as a Spiritual Practice ", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 86540, "product_subcategory": "Buddhism", "similar_product_ids": ["1569753008", "089281876X", "0385497911", "0517886200", "1570629838"], "review_helpful_votes": 11} +{"product_id": "B00005Y1U8", "customer_id": "A3JR7DSEOEK35H", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "After Everything Now This", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 89734, "product_subcategory": "General", "similar_product_ids": ["B00015HV74", "B00000AGLM", "B000006XLH", "B00006YXFX", "B000006XLF"], "review_helpful_votes": 1} +{"product_id": "B00005M1GK", "customer_id": "A3JZ4F6BY0PD1C", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Step It Up!", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 77518, "product_subcategory": "International", "similar_product_ids": ["B000000A0W", "B000000A1E", "B0000001HJ", "B0001XQ6FE", "B00015V59Y"], "review_helpful_votes": 1} +{"product_id": "0786866578", "customer_id": "A3K09ST87JCD6E", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dictionary of the Future", "review_rating": 5, "product_category": "Reference", "product_sales_rank": 98576, "product_subcategory": "Dictionaries & Thesauruses", "similar_product_ids": ["0399527494", "0312218990", "0887308570", "0887305946", "0786865237"], "review_helpful_votes": 2} +{"product_id": "0375406530", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 56756, "product_subcategory": "General", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} +{"product_id": "0375706410", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 3596, "product_subcategory": "General", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} +{"product_id": "1587880040", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 547875, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} +{"product_id": "1587883163", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 1880931, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} +{"product_id": "B00005RYCE", "customer_id": "A3KHPQTO7LFIVB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "I'm a Slave 4 U [Import CD]", "review_rating": 1, "product_category": "Pop", "product_sales_rank": 138936, "product_subcategory": "General", "similar_product_ids": ["B000069JAY", "B00005A7YT", "B000050X6R", "B0001B0VL6", "B000207NSU"], "review_helpful_votes": 3} +{"product_id": "B000051XY5", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The W", "review_rating": 4, "product_category": "Rap & Hip-Hop", "product_sales_rank": 37653, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00005U2LM", "B000002WPI", "B00001IVOR", "B000002HFU", "B000000OUJ"], "review_helpful_votes": 2} +{"product_id": "B000002WPH", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Enter The Wu-Tang (36 Chambers)", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 219871, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00001IVOR", "B000000OUJ", "B000002WU9", "B0000024JA", "B00005AQEQ"], "review_helpful_votes": 1} +{"product_id": "B000002WPI", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Enter the Wu-Tang (36 Chambers)", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 5528, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00001IVOR", "B000000OUJ", "B000002WU9", "B0000024JA", "B00005AQEQ"], "review_helpful_votes": 1} +{"product_id": "095253780X", "customer_id": "A3KN68AJ57XZBG", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Book", "product_title": "Around and About Paris, Volume 1", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 182164, "product_subcategory": "Europe", "similar_product_ids": ["0952537834", "0952537826", "1566564581", "0844201413", "0609804448"], "review_helpful_votes": 12} +{"product_id": "0385321414", "customer_id": "A3KTGMCRZJNWMA", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} +{"product_id": "0440418291", "customer_id": "A3KTGMCRZJNWMA", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} +{"product_id": "B000001EA8", "customer_id": "A3KXKMZ3U3PUD6", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Pre-Millennium Tension", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 9910, "product_subcategory": "General", "similar_product_ids": ["B000001E7V", "B000007P6K", "B000005HQN", "B00005LNH1", "B00000JWNY"], "review_helpful_votes": 6} +{"product_id": "0782140424", "customer_id": "A3KYVDMAPV5HM7", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Zoo Tycoon", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 120058, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["0782143571"], "review_helpful_votes": 9} +{"product_id": "6301801709", "customer_id": "A3L31489BCB1D7", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Wizards", "review_rating": 1, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 7670, "product_subcategory": "General", "similar_product_ids": ["0767836316", "B00003CWQI", "6305307156", "0792846818", "0767809548"], "review_helpful_votes": 4} +{"product_id": "B00005RYKU", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Glass House", "review_rating": 3, "product_category": "Mystery & Suspense", "product_sales_rank": 16524, "product_subcategory": "Suspense", "similar_product_ids": ["B00005UV34", "B000083C6I", "B00003CXI7", "B0001GF2D8", "B00005JMDZ"], "review_helpful_votes": 2} +{"product_id": "B00005RYP7", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Glass House", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 10111, "product_subcategory": "General", "similar_product_ids": ["B00005UV34", "B000083C6I", "B0001GF2D8", "B00003CXI7", "B00005JKIV"], "review_helpful_votes": 2} +{"product_id": "0671774778", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Section 31", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 335748, "product_subcategory": "Science Fiction", "similar_product_ids": ["0671774786", "0671774719", "0671774832", "0743491718", "074346754X"], "review_helpful_votes": 2} +{"product_id": "0201696231", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "QuarkXPress 4 for Macintosh", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 195266, "product_subcategory": "Graphics & Illustration", "similar_product_ids": ["0764502425", "0201696959", "0201713098", "0844226289", "0201782634"], "review_helpful_votes": 1} +{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} +{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 3} +{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 3} +{"product_id": "0842339523", "customer_id": "A3LGX5A0B5PQLX", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Book", "product_title": "Mark of the Lion ", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 3493, "product_subcategory": "Fiction", "similar_product_ids": ["1576738167", "0842335684", "0842319476", "084233498X", "084230052X"], "review_helpful_votes": 14} +{"product_id": "0963942972", "customer_id": "A3LQYVHNSEAKQX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Maui Revealed", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 229861, "product_subcategory": "United States", "similar_product_ids": ["0971727910", "0963942999", "0824826426", "0971727929", "0967007240"], "review_helpful_votes": 1} +{"product_id": "0971727902", "customer_id": "A3LQYVHNSEAKQX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Maui Revealed", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 56739, "product_subcategory": "United States", "similar_product_ids": ["0971727910", "0963942999", "0824826426", "0971727929", "0967007240"], "review_helpful_votes": 1} +{"product_id": "6303027016", "customer_id": "A3LU79BYMWZEW9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Good Morning, Vietnam", "review_rating": 3, "product_category": "Military & War", "product_sales_rank": 103, "product_subcategory": "Comedy", "similar_product_ids": ["6305144168", "B00000IQV7", "6305216088", "B00005AUJQ", "B00003CXA2"], "review_helpful_votes": 1} +{"product_id": "6305144176", "customer_id": "A3LU79BYMWZEW9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Good Morning, Vietnam", "review_rating": 3, "product_category": "Military & War", "product_sales_rank": 4895, "product_subcategory": "Comedy", "similar_product_ids": ["6305144168", "B00000IQV7", "6305216088", "B00005AUJQ", "B00003CXA2"], "review_helpful_votes": 1} +{"product_id": "0553713582", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 250314, "product_subcategory": "Leaders & Notable People", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} +{"product_id": "0609609874", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 214974, "product_subcategory": "Current Events", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} +{"product_id": "140004684X", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 6857, "product_subcategory": "Politics", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} +{"product_id": "0786866209", "customer_id": "A3M174IC0VXOS2", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Conflict of Interest ", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 518610, "product_subcategory": "Thrillers", "similar_product_ids": ["0786889837", "0758206186", "0451180062", "0525935878", "0451180216"], "review_helpful_votes": 10} +{"product_id": "0451181425", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Manhattans and Murder (Murder She Wrote)", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 213956, "product_subcategory": "Mystery", "similar_product_ids": ["0451185129", "0451183835", "0451187717", "0451184912", "0451194756"], "review_helpful_votes": 1} +{"product_id": "0451183835", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Murder, She Wrote", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 347183, "product_subcategory": "Mystery", "similar_product_ids": ["0451184912", "0451181425", "0451185129", "0451187717", "0451188209"], "review_helpful_votes": 0} +{"product_id": "0451194756", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Murder, She Wrote ", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 174336, "product_subcategory": "Mystery", "similar_product_ids": ["0451192915", "0451185129", "0451201523", "0451187717", "0451208323"], "review_helpful_votes": 0} +{"product_id": "0451194764", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Murder at the Powderhorn Ranch (Murder She Wrote 11)", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 436066, "product_subcategory": "Mystery", "similar_product_ids": ["0451194772", "0451194748", "0451211715", "0451207211", "0451208323"], "review_helpful_votes": 2} +{"product_id": "0451188209", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Palette for Murder (Murder She Wrote)", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 133051, "product_subcategory": "Mystery", "similar_product_ids": ["0451185129", "0451192915", "0451187717", "0451212843", "0451207211"], "review_helpful_votes": 2} +{"product_id": "0425169502", "customer_id": "A3MCQSIBV7QW8Q", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Darkest Knight (Star Wars", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 192945, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0425171531", "0425169057", "0425169499", "0425170616", "0425173135"], "review_helpful_votes": 3} +{"product_id": "0618127011", "customer_id": "A3MCW5KKOFAH3M", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "When Mountains Walked", "review_rating": 2, "product_category": "Literature & Fiction", "product_sales_rank": 111704, "product_subcategory": "General", "similar_product_ids": ["0861713540", "1573222674", "0375423079", "0395860326"], "review_helpful_votes": 2} +{"product_id": "0595204465", "customer_id": "A3MHPUCT09IHEX", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Five Points", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 527301, "product_subcategory": "Genre Fiction", "similar_product_ids": ["0452283612", "0374528993", "1560252758", "0805060049", "1560255218"], "review_helpful_votes": 10} +{"product_id": "B00005LB8B", "customer_id": "A3MOAWAHDRPPCI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "The Reduced Shakespeare Company - The Complete Works of William Shakespeare (Abridged)", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 11193, "product_subcategory": "General", "similar_product_ids": ["B00008NG9M", "B000777I88", "B0000DZTOM", "1557831572", "0881451487"], "review_helpful_votes": 3} +{"product_id": "B00008US5Q", "customer_id": "A3MOAWAHDRPPCI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "The Reduced Shakespeare Company - The Complete Works of William Shakespeare (Abridged)", "review_rating": 5, "product_category": "", "product_sales_rank": 2773, "product_subcategory": "", "similar_product_ids": ["B000777I88", "B00008NG9M", "B0000DZTOM", "1557831572", "0881451487"], "review_helpful_votes": 3} +{"product_id": "0375409076", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Leadership by the Book", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 401699, "product_subcategory": "Business", "similar_product_ids": ["0849996597", "1562924885", "0688039693", "068815428X", "0688170366"], "review_helpful_votes": 1} +{"product_id": "0688172393", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Leadership by the Book ", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 153795, "product_subcategory": "Business Life", "similar_product_ids": ["0849996597", "1562924885", "0688039693", "068815428X", "0688170366"], "review_helpful_votes": 1} +{"product_id": "0785264051", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws Of Leadership, Workbook", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 22349, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} +{"product_id": "0785274316", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws of Leadership", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 444, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} +{"product_id": "0785274766", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws of Leadership", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 162830, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} +{"product_id": "0785294279", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "21 Irrefutable Laws Of Leadership", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 914010, "product_subcategory": "Business", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} +{"product_id": "0486202410", "customer_id": "A3MOL7824BGDTR", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "An Atlas of Anatomy for Artists", "review_rating": 5, "product_category": "Arts & Photography", "product_sales_rank": 235641, "product_subcategory": "Graphic Design", "similar_product_ids": ["0486211045", "0486200825", "0195030958", "0823014010", "0486227081"], "review_helpful_votes": 2} +{"product_id": "B00003CY5J", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 9066, "product_subcategory": "Crime", "similar_product_ids": ["B00005UQ9T", "6305263248", "6305127697", "B0000B1OFL", "B00005LDDD"], "review_helpful_votes": 1} +{"product_id": "B000062XKK", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 83655, "product_subcategory": "Crime", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B000062XKL", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 20775, "product_subcategory": "Crime", "similar_product_ids": ["B00005UQ9T", "6305263248", "6305127697", "B0000B1OFL", "B0006J28KU"], "review_helpful_votes": 1} +{"product_id": "B00005OW09", "customer_id": "A3MUY2NYW3XGZ5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Trigun - The Complete Boxed Set", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 954, "product_subcategory": "General", "similar_product_ids": ["B00005QCW4", "B0001DCYCS", "B00008L3MH", "B0000639E0", "B00005NX1N"], "review_helpful_votes": 1} +{"product_id": "0691002703", "customer_id": "A3MWYPZBKL1NJ", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Orpheus and Power", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 435192, "product_subcategory": "Social Sciences", "similar_product_ids": ["1566395879", "080185251X", "0807854417", "0807844942", "0807849227"], "review_helpful_votes": 0} +{"product_id": "0446516570", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 182779, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} +{"product_id": "0446529931", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 501425, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} +{"product_id": "0446611913", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 24097, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} +{"product_id": "158621134X", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 120903, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} +{"product_id": "1586211366", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 421966, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} +{"product_id": "0944599273", "customer_id": "A3MZU97EKHUF4S", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Walt Disney's Uncle Scrooge & Donald Duck", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 58598, "product_subcategory": "Animals", "similar_product_ids": ["0944599281", "0944599249", "0944599001", "0944599028", "094459901X"], "review_helpful_votes": 7} +{"product_id": "B00000I2PG", "customer_id": "A3MZYSDR9DDSIH", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Lexicon Of Love", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 33997, "product_subcategory": "General", "similar_product_ids": ["B000001FD5", "B00005S84K", "B000005RYN", "B00005N8BG", "B00007MB2U"], "review_helpful_votes": 4} +{"product_id": "B0000057DL", "customer_id": "A3NCESLO69JCK4", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Monteverdi", "review_rating": 5, "product_category": "Classical", "product_sales_rank": 67577, "product_subcategory": "Featured Composers, A-Z", "similar_product_ids": ["B0000057CN", "B0000057CV", "B0000057F0", "B00000J9GR", "B00005K3P7"], "review_helpful_votes": 0} +{"product_id": "6301599330", "customer_id": "A3NIPOJ08YWIIL", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Faerie Tale Theatre - Little Red Riding Hood", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 12378, "product_subcategory": "General", "similar_product_ids": ["B00061UHZG", "B00061UHXI", "B00061UHYM", "B00061UHW4", "B00061UHVU"], "review_helpful_votes": 0} +{"product_id": "630575067X", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1599, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} +{"product_id": "630575070X", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 18465, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} +{"product_id": "6305750750", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition Boxed Set)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2872, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} +{"product_id": "B00003CX5P", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 28, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} +{"product_id": "B0000667J7", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition Boxed Set)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 16432, "product_subcategory": "Series & Sequels", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B00005JMQW"], "review_helpful_votes": 8} +{"product_id": "B00003CXI0", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 280, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "B00003CXI1", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Special Widescreen Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 337, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "B000062TU1", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Full Screen Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 1576, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "B000062TU2", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone - Spanish Edition", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 4207, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "B00006IRHA", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 40700, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "B00006IRHB", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 33519, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} +{"product_id": "0767802659", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Starship Troopers", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 8515, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B0001L3MI0", "B000244EMO"], "review_helpful_votes": 1} +{"product_id": "6304913176", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Starship Troopers", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 10313, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B000244EMO", "B0001L3MI0"], "review_helpful_votes": 1} +{"product_id": "B0000648WZ", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Starship Troopers (Special Edition)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 5059, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B000244EMO", "B0001L3MI0"], "review_helpful_votes": 1} +{"product_id": "6304502095", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Video", "product_title": "Repulsion", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 20289, "product_subcategory": "General", "similar_product_ids": ["B000069I09", "B00005JKP9", "B00005JKGO", "B0006IUE9I", "B0002KQNKE"], "review_helpful_votes": 4} +{"product_id": "B00005KHJM", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Wicker Man", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 4596, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} +{"product_id": "B00005KHJR", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Wicker Man (Limited Edition)", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 10451, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} +{"product_id": "B00005KHKX", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Wicker Man", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 23676, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} +{"product_id": "B00005KHL5", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Wicker Man (Unrated Edition)", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 9419, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} +{"product_id": "0446528382", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 4541, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "0446529869", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 488065, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "0446690686", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 12228, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "1586211722", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 485260, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "1586211730", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 275517, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "1586211749", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 393300, "product_subcategory": "Business", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} +{"product_id": "B00005V4Y7", "customer_id": "A3NOLKUXIEIKZJ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "Jackie's Back", "review_rating": 1, "product_category": "African American Cinema", "product_sales_rank": 22375, "product_subcategory": "Comedy", "similar_product_ids": ["B00008DDHJ", "B00007ELD8", "B0001NBMIU", "B0001DMUHM", "B00005LPZZ"], "review_helpful_votes": 0} +{"product_id": "B00005JJ1F", "customer_id": "A3NY5JFGYCD6JB", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Music", "product_title": "Copperhead", "review_rating": 2, "product_category": "Country", "product_sales_rank": 115167, "product_subcategory": "General", "similar_product_ids": ["B000002RI8", "B00005NQM6", "B000667FXI", "B00020H8Z8", "B0000A0DRX"], "review_helpful_votes": 3} +{"product_id": "0471874388", "customer_id": "A3NYKEMUTB1QEG", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Paul Wilmott on Quantitative Finance, 2 Volume Set", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 256270, "product_subcategory": "Finance", "similar_product_ids": ["0130090565", "0471654647", "0471394203", "0387004513", "0471499226"], "review_helpful_votes": 6} +{"product_id": "B0000296JC", "customer_id": "A3NZSZZORUXTXP", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Make Yourself", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 301940, "product_subcategory": "General", "similar_product_ids": ["B00005QG9J", "B00005RGO5", "B00018D5CQ", "B000050HU9", "B000002BSF"], "review_helpful_votes": 0} +{"product_id": "B00005L9AI", "customer_id": "A3O1W4XSMBT7OZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "010", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 262061, "product_subcategory": "Dance & DJ", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0141802820", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 990849, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} +{"product_id": "0141802847", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 686308, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} +{"product_id": "0451204948", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 28695, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} +{"product_id": "0670896764", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 237651, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} +{"product_id": "B00008RWPR", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 118872, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} +{"product_id": "0385471076", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "A Taste of Power ", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 82450, "product_subcategory": "Ethnic & National", "similar_product_ids": ["1556520743", "0717806677", "038533379X", "080700975X", "1556522304"], "review_helpful_votes": 3} +{"product_id": "B00004U8H5", "customer_id": "A3O4U7KTTGSFOU", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Prenatal Yoga", "review_rating": 5, "product_category": "", "product_sales_rank": 659, "product_subcategory": "", "similar_product_ids": ["B00008J2I7", "B000062XE2", "B00026L8VM", "B00009Y3SX", "B0001FZB6M"], "review_helpful_votes": 13} +{"product_id": "B00004U8H5", "customer_id": "A3O4U7KTTGSFOU", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Prenatal Yoga", "review_rating": 5, "product_category": "", "product_sales_rank": 659, "product_subcategory": "", "similar_product_ids": ["B00008J2I7", "B000062XE2", "B00026L8VM", "B00009Y3SX", "B0001FZB6M"], "review_helpful_votes": 13} +{"product_id": "B00000I9E4", "customer_id": "A3OAQ30458G3GA", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Music", "product_title": "Live at the Sydney Opera House", "review_rating": 4, "product_category": "Pop", "product_sales_rank": 7994, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B0000649PD", "B00000I2GJ", "B00005O6KC", "B00005A8B4", "B000059GIV"], "review_helpful_votes": 9} +{"product_id": "B00005PJCR", "customer_id": "A3OEI0MEVD6C3I", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Audioboxer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 23483, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B000091KV8", "B000066B4V", "B0000DD578", "B00065GWKQ", "B00006SFIM"], "review_helpful_votes": 1} +{"product_id": "0312978839", "customer_id": "A3OJ6WLOM4LJNT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Family Reunion", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 605287, "product_subcategory": "General", "similar_product_ids": ["0312315120", "0312306113", "1583145087", "0312989989", "1583141456"], "review_helpful_votes": 1} +{"product_id": "B000001BZQ", "customer_id": "A3ORUKYAHI5X2B", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Follow the Leader", "review_rating": 4, "product_category": "Rap & Hip-Hop", "product_sales_rank": 61989, "product_subcategory": "East Coast", "similar_product_ids": ["B000005HSR", "B000002O75", "B000002OKS", "B000002LEK", "B000003B7B"], "review_helpful_votes": 0} +{"product_id": "0345439945", "customer_id": "A3OZIAYOJ1DNS4", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "100 One-Night Reads ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 256277, "product_subcategory": "Books & Reading", "similar_product_ids": ["0140143505", "1570614350", "1929154178", "1570613818", "0816045585"], "review_helpful_votes": 2} +{"product_id": "B00005QG8W", "customer_id": "A3P214EYY6T8CK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Fake Sound of Progress", "review_rating": 5, "product_category": "Folk", "product_sales_rank": 21319, "product_subcategory": "Traditional British & Celtic Folk", "similar_product_ids": ["B00019PD0W", "B0000C23D6", "B0002A2VS2", "B0000A0WKG", "B00006GF9L"], "review_helpful_votes": 0} +{"product_id": "B00000C2EM", "customer_id": "A3P3GNT2X93PBV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Postcards from Rio", "review_rating": 4, "product_category": "Jazz", "product_sales_rank": 59348, "product_subcategory": "Brazilian Jazz", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "B000001ALS", "customer_id": "A3P68SYSHAB9GD", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Emperors of Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 6457, "product_subcategory": "Classic R&B", "similar_product_ids": ["B000001AKK", "B000001A8J", "B00005NSXV", "B00001QGU7", "0815412185"], "review_helpful_votes": 0} +{"product_id": "B00000DRAD", "customer_id": "A3P6BXE4KG8L5J", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Legendary Masters", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 50049, "product_subcategory": "Oldies", "similar_product_ids": ["B00000I8AJ", "B00005B179", "B00000DRAR", "B000002P1T", "B00000JJAU"], "review_helpful_votes": 0} +{"product_id": "B0000584U2", "customer_id": "A3PAAIPUN554CC", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Relentless Beats", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 109482, "product_subcategory": "General", "similar_product_ids": ["B00005Y1TT", "B00005171U", "B00005UPP4"], "review_helpful_votes": 0} +{"product_id": "1930693931", "customer_id": "A3PB38VN8E5FA4", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "What Color Is Your Scarf?", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 1255218, "product_subcategory": "Relationships", "similar_product_ids": [], "review_helpful_votes": 4} +{"product_id": "B00005A46T", "customer_id": "A3PC0I1XLBDSW", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 4, "product_category": "Hard Rock & Metal", "product_sales_rank": 1154, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B00000JCOV", "B0001NBMBC", "B00004WK3A", "B0000787EO", "B00007BHOE"], "review_helpful_votes": 0} +{"product_id": "B00005NNNG", "customer_id": "A3PC0I1XLBDSW", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 4, "product_category": "Hard Rock & Metal", "product_sales_rank": 430847, "product_subcategory": "Alternative Metal", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "B000005IYF", "customer_id": "A3PEMQAM8WICIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Scott Joplin", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 2893, "product_subcategory": "General", "similar_product_ids": ["B000003QWN", "0486258076", "B00000DD02", "B00009PJSR", "B00009PJST"], "review_helpful_votes": 3} +{"product_id": "0140568085", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar! (Picture Puffins)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 268149, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} +{"product_id": "0525452761", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 151545, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} +{"product_id": "0525458344", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 27631, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} +{"product_id": "0525460888", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1793838, "product_subcategory": "Baby-3", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "B00004SVKL", "customer_id": "A3PG5CSK8Y4ECT", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Never Never Land", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 6178, "product_subcategory": "General", "similar_product_ids": ["B00005AWDF", "B0002JP4K0", "B00006G99J", "B0000TSQX4", "B00014X8E0"], "review_helpful_votes": 1} +{"product_id": "0849938635", "customer_id": "A3PK971R04XQAX", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Oath", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 109802, "product_subcategory": "Fiction", "similar_product_ids": ["0849944775", "0842361715", "0891076182", "0891075275", "0849976170"], "review_helpful_votes": 3} +{"product_id": "0849308216", "customer_id": "A3PU1RNZVISZPG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "High-Speed Cisco Networks", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 578941, "product_subcategory": "Certification Central", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "B0000633VJ", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Emergence (Uncut)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 35985, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} +{"product_id": "B0000633VK", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Emergence (Edited)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 62316, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} +{"product_id": "B0000640SV", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "Dragon Ball Z - Majin Buu - Emergence", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 34137, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} +{"product_id": "B00005T32J", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Defiance (Uncut)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 38158, "product_subcategory": "Characters & Series", "similar_product_ids": ["B00005UF7Q", "B0000633S4", "B00005UF7R", "B00005NB92", "B00005K9NY"], "review_helpful_votes": 6} +{"product_id": "B0000633S6", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Dragon Ball Z - Majin Buu - Defiance", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 31737, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B00005UF7R", "B00005NB92", "B0000640SW", "B000066731"], "review_helpful_votes": 6} +{"product_id": "6303991408", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 2880, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} +{"product_id": "B00005TSMN", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4351, "product_subcategory": "Animals", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} +{"product_id": "B00005TSMQ", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 15562, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} +{"product_id": "B00005TSMR", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto Spanish Dubbed", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 3329, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} +{"product_id": "B00005V8ST", "customer_id": "A3PXXIO9GJZ1K", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Always Got Tonight", "review_rating": 4, "product_category": "Rock", "product_sales_rank": 14038, "product_subcategory": "General", "similar_product_ids": ["B000002MWG", "B00000AG8O", "B000002LGI", "B000002MH7", "B000002N9X"], "review_helpful_votes": 2} +{"product_id": "B00004SQZG", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Last of the Great 20th Century Composers", "review_rating": 1, "product_category": "Indie Music", "product_sales_rank": 56307, "product_subcategory": "Rap & Hip-Hop", "similar_product_ids": ["B00005NFK7", "B00009KU8F", "B000002JPY", "B00005RTSV", "B00064AEJW"], "review_helpful_votes": 2} +{"product_id": "B00000J7KT", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "The Year of the Backslap", "review_rating": 3, "product_category": "Rap & Hip-Hop", "product_sales_rank": 361395, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "B00004R8PO", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Hip Hop Underground's Finest", "review_rating": 3, "product_category": "Rap & Hip-Hop", "product_sales_rank": 150824, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B0000064SD", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "HII", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 19012, "product_subcategory": "General", "similar_product_ids": ["B000003C04", "B00030EEO0", "B000067CMV", "B00000JG2X", "B0002WZT20"], "review_helpful_votes": 0} +{"product_id": "B00001IVOH", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Soul Survivor", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 123928, "product_subcategory": "Rap & Hip-Hop", "similar_product_ids": ["B000002HFW", "B000002H84", "B0000D9Y5N", "B00005AV09", "B000089CGF"], "review_helpful_votes": 0} +{"product_id": "0743442849", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Addicted ", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 4275, "product_subcategory": "Genre Fiction", "similar_product_ids": ["074346270X", "0743457021", "0743476247", "0743482387", "0743442903"], "review_helpful_votes": 0} +{"product_id": "0967460174", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Addicted", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 801676, "product_subcategory": "Thrillers", "similar_product_ids": ["074346270X", "0743457021", "0743476247", "0743482387", "0743442903"], "review_helpful_votes": 0} +{"product_id": "0375757430", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Shades of Jade ", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 167112, "product_subcategory": "Thrillers", "similar_product_ids": ["0870678655", "075820468X", "0375757449", "0967878918", "0743258169"], "review_helpful_votes": 0} +{"product_id": "0060081325", "customer_id": "A3Q80Q6YFP5W6Q", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "A Multitude of Sins", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 890779, "product_subcategory": "General", "similar_product_ids": ["0679776680", "0312423799", "0394757009", "031242227X", "0375726012"], "review_helpful_votes": 10} +{"product_id": "037572656X", "customer_id": "A3Q80Q6YFP5W6Q", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "A Multitude of Sins", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 111793, "product_subcategory": "General", "similar_product_ids": ["0679776680", "0312423799", "0394757009", "031242227X", "0375726012"], "review_helpful_votes": 10} +{"product_id": "B000006XCK", "customer_id": "A3Q83VI243WI7U", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "The Byrds [1973]", "review_rating": 4, "product_category": "Classic Rock", "product_sales_rank": 89795, "product_subcategory": "General", "similar_product_ids": ["B00000721Z", "B0001K2LWY", "B00004OCE8", "B0000ACY0Y", "B0001WPSJ0"], "review_helpful_votes": 5} +{"product_id": "031218008X", "customer_id": "A3QBA6UYOZYP3T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "One Thousand White Women ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 54287, "product_subcategory": "Genre Fiction", "similar_product_ids": ["1594480001", "0743227441", "0312422156", "0345416260", "015602943X"], "review_helpful_votes": 3} +{"product_id": "0312199430", "customer_id": "A3QBA6UYOZYP3T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "One Thousand White Women ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 648, "product_subcategory": "Genre Fiction", "similar_product_ids": ["1594480001", "0743227441", "0312422156", "0345416260", "015602943X"], "review_helpful_votes": 3} +{"product_id": "B000001C6G", "customer_id": "A3QCX67A649QAU", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Eaten Back to Life", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 47079, "product_subcategory": "Death Metal", "similar_product_ids": ["B000001C6W", "B000001C5S", "B000001C7Z", "B0000060ZW", "B000001CAL"], "review_helpful_votes": 2} +{"product_id": "B00004YLAR", "customer_id": "A3QE37MQRFEHYL", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "MIA", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 9741, "product_subcategory": "General", "similar_product_ids": ["B000008EBJ", "B00004YLAP", "B000000LZ2", "B000000JO3", "B000000LXS"], "review_helpful_votes": 1} +{"product_id": "0814471218", "customer_id": "A3QGIY1WPM8LF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Ultimate Web Developer's Sourcebook", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 1126702, "product_subcategory": "Web Development", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0814471218", "customer_id": "A3QGIY1WPM8LF9", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Ultimate Web Developer's Sourcebook", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 1126702, "product_subcategory": "Web Development", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "074323538X", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 2736, "product_subcategory": "Careers", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} +{"product_id": "0743525906", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 383422, "product_subcategory": "Business", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} +{"product_id": "0743525914", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 212095, "product_subcategory": "Parenting & Families", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} +{"product_id": "0071383832", "customer_id": "A3QJE0749PJJJF", "review_date": {"$date": 1013644800000}, "review_votes": 45, "product_group": "Book", "product_title": "The Fat Flush Plan", "review_rating": 4, "product_category": "Health, Mind & Body", "product_sales_rank": 663, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0071407944", "0071433678", "0071440682", "0071414975", "0767920457"], "review_helpful_votes": 44} +{"product_id": "0972488936", "customer_id": "A3QJE0749PJJJF", "review_date": {"$date": 1013644800000}, "review_votes": 45, "product_group": "Book", "product_title": "The Fat Flush Plan", "review_rating": 4, "product_category": "Health, Mind & Body", "product_sales_rank": 113814, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0071407944", "0071433678", "0071440682", "0071414975", "0767920457"], "review_helpful_votes": 44} +{"product_id": "B00002Z845", "customer_id": "A3QLQB0FBL3Q8J", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Hard Volume", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 147708, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0000040OX", "B0000040P3", "B00002Z847", "B00004KS3P", "B00005NHH9"], "review_helpful_votes": 1} +{"product_id": "0800632753", "customer_id": "A3QVAKVRAH657N", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Video", "product_title": "Bonhoeffer - Agent of Grace", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 16895, "product_subcategory": "Leaders & Notable People", "similar_product_ids": ["B0001GH7W2", "B0000ACNPN", "6304267908", "0684838273", "0684815001"], "review_helpful_votes": 25} +{"product_id": "0679721886", "customer_id": "A3QW0OMPL43OHN", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Woman Warrior ", "review_rating": 1, "product_category": "Biographies & Memoirs", "product_sales_rank": 2535, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0679723285", "0140086838", "1577661176", "0814402178", "0295955252"], "review_helpful_votes": 6} +{"product_id": "0808589768", "customer_id": "A3QW0OMPL43OHN", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Woman Warrior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 609373, "product_subcategory": "Social Sciences", "similar_product_ids": ["0679723285", "0140086838", "1577661176", "0814402178", "0295955252"], "review_helpful_votes": 6} +{"product_id": "B000003RSB", "customer_id": "A3QWNQ2WA7QZYJ", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Music", "product_title": "Lazer Guided Melodies", "review_rating": 3, "product_category": "Alternative Rock", "product_sales_rank": 40542, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002VUG", "B000002VTE", "B00008WI7A", "B00005OAIL", "B000000EU8"], "review_helpful_votes": 5} +{"product_id": "B00004ZEJH", "customer_id": "A3QWNQ2WA7QZYJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Don't Let Go", "review_rating": 3, "product_category": "Rock", "product_sales_rank": 45486, "product_subcategory": "Blues Rock", "similar_product_ids": ["B00005A8B8", "B000002VM1", "B000002VKE", "B0002XEDOE", "B000000XD4"], "review_helpful_votes": 3} +{"product_id": "1569552436", "customer_id": "A3R1FQ5J1279A3", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Why Do Catholics Genuflect?", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 395217, "product_subcategory": "Christianity", "similar_product_ids": ["0879736933", "0764553917", "0898704782", "0465092624", "0898705533"], "review_helpful_votes": 10} +{"product_id": "6300213714", "customer_id": "A3RC3ORILDUJDN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Warriors", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 6871, "product_subcategory": "General", "similar_product_ids": ["B0000696IC", "B00005NKSN", "0783227876", "B00002E237", "B00004RE45"], "review_helpful_votes": 2} +{"product_id": "B0000541AM", "customer_id": "A3RC3ORILDUJDN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Warriors", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 1139, "product_subcategory": "General", "similar_product_ids": ["B0000696IC", "B00005NKSN", "0783227876", "B00002E237", "B00004RE45"], "review_helpful_votes": 2} +{"product_id": "0345424719", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 9492, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} +{"product_id": "034543479X", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 413221, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} +{"product_id": "0375501371", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 461572, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} +{"product_id": "B00005N7AM", "customer_id": "A3REH5JO0KNEUX", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Pat Ortman", "review_rating": 4, "product_category": "Indie Music", "product_sales_rank": 312034, "product_subcategory": "Alternative Rock", "similar_product_ids": [], "review_helpful_votes": 3} +{"product_id": "0521509173", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin (Black Bonded leather)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 201408, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204"], "review_helpful_votes": 5} +{"product_id": "0521509181", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin (Black Calfskin Leather)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 212695, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204", "1400054184"], "review_helpful_votes": 5} +{"product_id": "052150919X", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin Reference Edition with Glossary and Concordance Burgundy calfskin KWM267", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 990503, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204"], "review_helpful_votes": 5} +{"product_id": "1885478747", "customer_id": "A3RT6G1ZAE6WDE", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Fate (Love Spectrum Romance)", "review_rating": 3, "product_category": "Romance", "product_sales_rank": 582828, "product_subcategory": "Multicultural", "similar_product_ids": ["1585710938", "158571108X", "1585710288", "158571092X", "0060747730"], "review_helpful_votes": 2} +{"product_id": "B00005NB9Z", "customer_id": "A3RXXDCXJA1XIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "The Visitors", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 8567, "product_subcategory": "General", "similar_product_ids": ["B00005NB9Y", "B0000A1HQP", "B00005OSLQ", "B00007L4OM", "B0000897B7"], "review_helpful_votes": 3} +{"product_id": "B00005U18K", "customer_id": "A3RXXDCXJA1XIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "The Visitors", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 29700, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005NB9Y", "B0000A1HQP", "B00005OSLQ", "B00007L4OM", "B0000897B7"], "review_helpful_votes": 3} +{"product_id": "043936213X", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0590353403", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0786222727", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281751", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281956", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0939173344", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "B00004Z4T0", "customer_id": "A3S5C7Y0WT2Q9N", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Jennifer Lopez - Feelin' So Good", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 11653, "product_subcategory": "General", "similar_product_ids": ["B000087EXR", "B0000DJZ83", "B0000APVH7", "B00005NRO0", "B0000TWMMA"], "review_helpful_votes": 2} +{"product_id": "B00005QFE5", "customer_id": "A3SBVTRU7301II", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Road Home", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 3110, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005JM6H", "0767853512", "B00002RAPT", "B00030590I", "B00004Z1FF"], "review_helpful_votes": 2} +{"product_id": "B00005QFF1", "customer_id": "A3SBVTRU7301II", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Road Home", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 1369, "product_subcategory": "By Country", "similar_product_ids": ["B00005JM6H", "0767853512", "B00002RAPT", "B00030590I", "B00004Z1FF"], "review_helpful_votes": 2} +{"product_id": "B00000261W", "customer_id": "A3SFN7ECK78CEV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Deed Is Done", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 60254, "product_subcategory": "Southern Rock", "similar_product_ids": ["B0000025D5", "B0000025O1", "B000002Z1Q", "B000024PKN"], "review_helpful_votes": 2} +{"product_id": "B000050HZO", "customer_id": "A3SIBP6L8S5KJJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "No Name Face", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 432, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B00006JJ1X", "B0007PALCU", "B00006ALCK", "B00000J6BR", "B00005K9T9"], "review_helpful_votes": 1} +{"product_id": "B000050HZP", "customer_id": "A3SIBP6L8S5KJJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "No Name Face", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 333274, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B00006JJ1X", "B0007PALCU", "B00006ALCK", "B00000J6BR", "B00005K9T9"], "review_helpful_votes": 1} +{"product_id": "0140232257", "customer_id": "A3SISHZPSJRA98", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Monster ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 57056, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0060922915", "1587170949", "1556524277", "0385474326", "1576870723"], "review_helpful_votes": 1} +{"product_id": "0735612889", "customer_id": "A3SKXXZKVPCA2T", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Inside C# (With CD-ROM)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 408801, "product_subcategory": "Programming", "similar_product_ids": ["0735615543", "0735614229", "0735613702", "0735612900", "0735619093"], "review_helpful_votes": 2} +{"product_id": "0735616485", "customer_id": "A3SKXXZKVPCA2T", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Inside C#, Second Edition", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 104672, "product_subcategory": "Programming", "similar_product_ids": ["0735615543", "0735614229", "0735613702", "0735612900", "0735619093"], "review_helpful_votes": 2} +{"product_id": "0767908201", "customer_id": "A3SLDKL6UJLK5P", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Inconceivable ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 25732, "product_subcategory": "Specific Groups", "similar_product_ids": ["0316172294", "1893290395", "0684855224", "0142002011", "B0001ARFEI"], "review_helpful_votes": 7} +{"product_id": "006447030X", "customer_id": "A3T79FZYA1SMZ0", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Rifles for Watie", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 65246, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0425102416", "0140341587", "0440442508", "0689715714", "0618250743"], "review_helpful_votes": 5} +{"product_id": "0690049072", "customer_id": "A3T79FZYA1SMZ0", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Rifles for Watie", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 252113, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0140341587", "0425102416", "0440442508", "0689715714", "0618250743"], "review_helpful_votes": 5} +{"product_id": "0060935456", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down (Perennial Classics)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 328957, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} +{"product_id": "0380002930", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 723, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} +{"product_id": "068483605X", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down (Scribner Classics)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 24193, "product_subcategory": "General", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} +{"product_id": "1559352310", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down/Audio Cassettes (Audio csst ed)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 855366, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} +{"product_id": "1565115864", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down Cass", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1121326, "product_subcategory": "General", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} +{"product_id": "1569902089", "customer_id": "A3TMFREIQ35H1X", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Polypropylene Handbook", "review_rating": 4, "product_category": "Engineering", "product_sales_rank": 829140, "product_subcategory": "Chemical", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0393320685", "customer_id": "A3TMFREIQ35H1X", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Chemical Tree", "review_rating": 4, "product_category": "Science", "product_sales_rank": 95053, "product_subcategory": "Chemistry", "similar_product_ids": ["0486233421", "0486659771", "0801866103", "073820594X", "0486610535"], "review_helpful_votes": 2} +{"product_id": "B0000027RL", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Ten", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 1023, "product_subcategory": "General", "similar_product_ids": ["B0000028UK", "B000003TA4", "B000002AZ8", "B000002G2B", "B000002IU3"], "review_helpful_votes": 1} +{"product_id": "0553280414", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 996, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "0553450549", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 622129, "product_subcategory": "Children's Books", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "0684833662", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace (Scribner Classics)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 23067, "product_subcategory": "General", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "0764585789", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace (Cliffs Notes)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 104583, "product_subcategory": "World Literature", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "0791056635", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "John Knowles's a Separate Peace (Bloom's Modern Critical Interpretations)", "review_rating": 5, "product_category": "Reference", "product_sales_rank": 1186382, "product_subcategory": "Education", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "1883332494", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 73885, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "1883332761", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 204500, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} +{"product_id": "6303503381", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Video", "product_title": "Joseph Campbell and the Power of Myth - Vols. 1-6", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 8275, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["B00005Y71V", "B00005Y71U", "0385418868", "B000063K0N", "0691017840"], "review_helpful_votes": 14} +{"product_id": "B00005MEVQ", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "DVD", "product_title": "Joseph Campbell and the Power of Myth", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 1382, "product_subcategory": "General", "similar_product_ids": ["B00005Y71V", "B00005Y71U", "0385418868", "B000063K0N", "0691017840"], "review_helpful_votes": 14} +{"product_id": "0195020588", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The New Oxford Book of American Verse (Oxford Books of Verse)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 439017, "product_subcategory": "Poetry", "similar_product_ids": ["0192141821", "0198121369", "0060540419", "0393041301", "0071427791"], "review_helpful_votes": 1} +{"product_id": "0345335511", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Pawn of Prophecy (The Belgariad, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 21869, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345335457", "0345335708", "0345338715", "0345352661", "0345358805"], "review_helpful_votes": 2} +{"product_id": "0808587226", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Pawn of Prophecy (Belgariad)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 1033362, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0345335457", "0345335708", "0345338715", "0345352661", "0345358805"], "review_helpful_votes": 2} +{"product_id": "B00004WG1R", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "My Favorite Year", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 22977, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} +{"product_id": "B00004WG1S", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "My Favorite Year (Widescreen Edition)", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 20025, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} +{"product_id": "B0000648ZX", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "My Favorite Year", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 2980, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} +{"product_id": "006019832X", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 205543, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} +{"product_id": "006103097X", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 290175, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} +{"product_id": "0066214009", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 1243584, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} +{"product_id": "0060987464", "customer_id": "A3TUQDFYUNFXLG", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "The Long Hard Road Out of Hell", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 17997, "product_subcategory": "Arts & Literature", "similar_product_ids": ["0859653293", "B00005U2JL", "B00000AFGM", "B000001Y5X", "B000001Y2U"], "review_helpful_votes": 15} +{"product_id": "0743244281", "customer_id": "A3TXJL518S7UWI", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Barry Trotter and the Unauthorized Parody", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 98495, "product_subcategory": "Humor", "similar_product_ids": ["0451452615", "1593600259", "0671541447", "0972393633", "1571744126"], "review_helpful_votes": 2} +{"product_id": "6302595916", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol (Colorized)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 27980, "product_subcategory": "Fantasy", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "6302914485", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 5394, "product_subcategory": "Adapted from Books", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "B000007P8Z", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 51981, "product_subcategory": "General", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "B000007SXQ", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol (50th Anniversary Edition)", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 20384, "product_subcategory": "General", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "B00000F168", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (Colorized Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 14770, "product_subcategory": "3-6 Years", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "B00000JT8Z", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (Original B&W Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4266, "product_subcategory": "7-9 Years", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "B00005TPCG", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (50th Anniversary Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 28748, "product_subcategory": "Family Films", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} +{"product_id": "0812522729", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Children of the Night", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 172069, "product_subcategory": "Fantasy", "similar_product_ids": ["0765313170", "0812521145", "0812519655", "0671578057", "0756401615"], "review_helpful_votes": 1} +{"product_id": "031225346X", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Prometheus Deception", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 291444, "product_subcategory": "Thrillers", "similar_product_ids": ["0312982518", "0312989385", "0312973055", "0312981589", "0312982615"], "review_helpful_votes": 1} +{"product_id": "0312978367", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Prometheus Deception", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 38413, "product_subcategory": "Thrillers", "similar_product_ids": ["0312982518", "0312989385", "0312973055", "0312981589", "0553262564"], "review_helpful_votes": 1} +{"product_id": "0886775302", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Blood Lines (Daw Book Collectors)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 247356, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0060572965", "0060572973", "0425197484", "0553587072", "042519485X"], "review_helpful_votes": 2} +{"product_id": "1579900216", "customer_id": "A3UAAWZH8ESADD", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Laminated Designs in Wood", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 728696, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": [], "review_helpful_votes": 4} +{"product_id": "0804119309", "customer_id": "A3UC0TNMOROOZF", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Last Knight", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 134533, "product_subcategory": "General", "similar_product_ids": ["0804118272", "044900127X", "0804117586", "0804119317", "0345447174"], "review_helpful_votes": 0} +{"product_id": "0768902967", "customer_id": "A3UDY5C0SCQIB9", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Peterson's Scholarships and Loans for Adult Students", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 509257, "product_subcategory": "Education", "similar_product_ids": [], "review_helpful_votes": 7} +{"product_id": "B0000076AV", "customer_id": "A3UH6L4XX59HGX", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Long Riders", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 58143, "product_subcategory": "Blues Rock", "similar_product_ids": ["B000056H2J", "B000002L7L", "B000002N0X", "B000002KCO", "B000002KC4"], "review_helpful_votes": 4} +{"product_id": "1555973140", "customer_id": "A3UHMX027J2Z1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Halls of Fame", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 784305, "product_subcategory": "Social Sciences", "similar_product_ids": ["1555973752", "1555974074", "0970367201", "1555973035", "0880014776"], "review_helpful_votes": 0} +{"product_id": "1555973779", "customer_id": "A3UHMX027J2Z1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Halls of Fame", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 48215, "product_subcategory": "World Literature", "similar_product_ids": ["1555973752", "1555974074", "0970367201", "1555973035", "0880014776"], "review_helpful_votes": 0} +{"product_id": "0385334524", "customer_id": "A3UKGCS3FIO8UD", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blast from the Past", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 536562, "product_subcategory": "Thrillers", "similar_product_ids": ["0552999458", "0552999954", "0751510114", "0552146986", "0312194722"], "review_helpful_votes": 0} +{"product_id": "0942397061", "customer_id": "A3UKGQ6KRYYRVM", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "God Is My Co-Pilot", "review_rating": 5, "product_category": "", "product_sales_rank": 79442, "product_subcategory": "", "similar_product_ids": ["1560985410", "0394747410", "0440204321", "1574885545", "0671636030"], "review_helpful_votes": 7} +{"product_id": "0064470733", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "One Fat Summer (Ursula Nordstrom Book)", "review_rating": 2, "product_category": "Children's Books", "product_sales_rank": 8461, "product_subcategory": "People & Places", "similar_product_ids": ["0553263218", "0439286034", "0440944597", "0064407314", "0064470393"], "review_helpful_votes": 0} +{"product_id": "0141312351", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 40850, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} +{"product_id": "0525461663", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 432356, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} +{"product_id": "0613359488", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 838665, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} +{"product_id": "0440206324", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Island", "review_rating": 3, "product_category": "Teens", "product_sales_rank": 54872, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440413796", "0440407532", "0440227194", "0385746474", "0440219205"], "review_helpful_votes": 0} +{"product_id": "0763607762", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Because of Winn-Dixie)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 8322, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} +{"product_id": "0763616052", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Because of Winn-Dixie)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 528, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} +{"product_id": "0786236655", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Thorndike Press Large Print Juvenile Series)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1193987, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} +{"product_id": "0807261866", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 182263, "product_subcategory": "Children's Books", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} +{"product_id": "6302744679", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Star Trek - The Next Generation, Episode 25", "review_rating": 3, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 44828, "product_subcategory": "Space Adventure", "similar_product_ids": [], "review_helpful_votes": 6} +{"product_id": "0064472345", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Vanishing (Laura Geringer Books (Paperback))", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 144059, "product_subcategory": "People & Places", "similar_product_ids": ["0440415780", "0689866364", "0060502495", "037582233X", "0786851481"], "review_helpful_votes": 0} +{"product_id": "0064472345", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Vanishing (Laura Geringer Books (Paperback))", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 144059, "product_subcategory": "People & Places", "similar_product_ids": ["0440415780", "0689866364", "0060502495", "037582233X", "0786851481"], "review_helpful_votes": 0} +{"product_id": "0152928774", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harris and Me", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 291391, "product_subcategory": "People & Places", "similar_product_ids": ["0440405246", "0440413796", "0440407532", "0440410258", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0316142034", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Snowboard Maverick ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 402792, "product_subcategory": "Sports & Activities", "similar_product_ids": ["0316135127", "0316142417", "0316135496", "0316140023", "0316140538"], "review_helpful_votes": 0} +{"product_id": "0316807222", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee (Newbery Medal Book)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 45196, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0316809063", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 685, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0345370775", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 5356, "product_subcategory": "Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} +{"product_id": "0374378487", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 140908, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480095", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 1401, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480125", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting, 25th Anniversary Edition (Sunburst Book)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 82996, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480133", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 679151, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0385086954", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 78059, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} +{"product_id": "0385325002", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 197367, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} +{"product_id": "0394588169", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 29311, "product_subcategory": "Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} +{"product_id": "0394588304", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 466629, "product_subcategory": "Mystery & Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} +{"product_id": "0440227623", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hate You", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 627642, "product_subcategory": "People & Places", "similar_product_ids": ["0066239621", "0385731191", "0385729774", "0439324599", "0689817851"], "review_helpful_votes": 0} +{"product_id": "0440413796", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 24609, "product_subcategory": "Literature", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} +{"product_id": "0553526200", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 447812, "product_subcategory": "Children's Books", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} +{"product_id": "0590366440", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 4, "product_category": "Nonfiction", "product_sales_rank": 809759, "product_subcategory": "Education", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0590373544", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 4, "product_category": "Nonfiction", "product_sales_rank": 734802, "product_subcategory": "Education", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0609810901", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie (Los Jet De Plaza & Janes. Biblioteca De Stephen King. 102, 8)", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1244143, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} +{"product_id": "0671039725", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 72173, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} +{"product_id": "0671039733", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1234187, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} +{"product_id": "0689820836", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Real American Girls Tell Their Own Stories ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 1142523, "product_subcategory": "People & Places", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0805061053", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Both Sides Now", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 881673, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440229219", "0440228794", "0064473473", "014131088X", "0440416027"], "review_helpful_votes": 0} +{"product_id": "0807205958", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 171405, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0807275530", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 393142, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0833585568", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 519286, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "1410400204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Heart of the Lonely Exile (An Emerald Ballad, 2)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1385657, "product_subcategory": "General", "similar_product_ids": ["1556611102", "1556611137", "1556611145", "0842314792", "0849943914"], "review_helpful_votes": 0} +{"product_id": "1410400204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Heart of the Lonely Exile (An Emerald Ballad, 2)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1385657, "product_subcategory": "General", "similar_product_ids": ["1556611102", "1556611137", "1556611145", "0842314792", "0849943914"], "review_helpful_votes": 0} +{"product_id": "1883332648", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 407683, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "8401499666", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1640707, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} +{"product_id": "0440227623", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hate You", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 627642, "product_subcategory": "People & Places", "similar_product_ids": ["0066239621", "0385731191", "0385729774", "0439324599", "0689817851"], "review_helpful_votes": 0} +{"product_id": "0689206518", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Mrs. Frisby and the Rats of NIMH", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 209256, "product_subcategory": "Animals", "similar_product_ids": ["0064402452", "0440498058", "0689711816", "0064403874", "0064401847"], "review_helpful_votes": 0} +{"product_id": "0689710682", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Mrs. Frisby and the Rats of Nimh (Aladdin Fantasy)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 3351, "product_subcategory": "Animals", "similar_product_ids": ["0064402452", "0440498058", "0689711816", "0064403874", "1557345236"], "review_helpful_votes": 0} +{"product_id": "0027594556", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 54623, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0140366695", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Puffin Classics)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 652238, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0440206324", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Island", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 54872, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440413796", "0440407532", "0440227194", "0385746474", "0440219205"], "review_helpful_votes": 1} +{"product_id": "0448060272", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild and Other Stories (Illustrated Junior Library)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 988203, "product_subcategory": "Literature", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0486264726", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Dover Thrift Editions)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 195561, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0670867969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Whole Story)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 400161, "product_subcategory": "Literature", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0812504321", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 3344, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} +{"product_id": "0448089386", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mystery at Devil's Paw, (Hardy Boys Mystery Stories)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 251103, "product_subcategory": "Literature", "similar_product_ids": ["044808936X", "0448089378", "0448089408", "0448089416", "0448089335"], "review_helpful_votes": 0} +{"product_id": "0152019898", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Captain's Dog", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 498007, "product_subcategory": "Animals", "similar_product_ids": ["1561451908", "0824954424", "0805063684", "1590780280", "1556523742"], "review_helpful_votes": 1} +{"product_id": "0152026967", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Captain's Dog", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 142278, "product_subcategory": "Animals", "similar_product_ids": ["1561451908", "0824954424", "0805063684", "1590780280", "1556523742"], "review_helpful_votes": 1} +{"product_id": "0375759239", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Modern Library Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 207791, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "0486295060", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Dover Thrift Editions)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 176991, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "0486405524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Dover Children's Thrift Classics)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 990009, "product_subcategory": "Literature", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "0486419371", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "War of the Worlds (Dover Large Print Classics)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 282278, "product_subcategory": "General", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "B0000714I5", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Halloween - Resurrection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 13936, "product_subcategory": "General", "similar_product_ids": ["6305291446", "B00004Y632", "B00005OKQF", "6305971099", "B00005LC4Q"], "review_helpful_votes": 0} +{"product_id": "0553213385", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Bantam Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 67426, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "067103443X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Chocolate-Covered Contest (NANCY DREW ON CAMPUS)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 263954, "product_subcategory": "Literature", "similar_product_ids": ["0671872087", "0743437446", "0671027875", "0671001213", "0671505025"], "review_helpful_votes": 2} +{"product_id": "0688131379", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Books of Wonder)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 148955, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "0812505158", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Tor Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 333, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "0899663761", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "War of the Worlds", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 547989, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} +{"product_id": "1576465128", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2800303, "product_subcategory": "Authors, A-Z", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "0141306424", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Secret Life of Amanda K. Woods", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 176974, "product_subcategory": "People & Places", "similar_product_ids": ["0689817215", "0439339022", "0439372941", "0064410226", "0763617229"], "review_helpful_votes": 0} +{"product_id": "0316140643", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Football Fugitive (Matt Christopher Sports Classics)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 366780, "product_subcategory": "Sports & Activities", "similar_product_ids": ["0316140775", "0316140589", "0316137952", "0316143073", "0316141674"], "review_helpful_votes": 0} +{"product_id": "0345378490", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Congo", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 548799, "product_subcategory": "Thrillers", "similar_product_ids": ["0345353145", "0345370775", "034540288X", "0345402871", "0060541814"], "review_helpful_votes": 0} +{"product_id": "0374378487", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 140908, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480095", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1401, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480125", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting, 25th Anniversary Edition (Sunburst Book)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82996, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0374480133", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 679151, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0380733021", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "All Alone in the Universe", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 285144, "product_subcategory": "Literature", "similar_product_ids": ["0375829164", "043912042X", "0064405710", "0064405176", "0380713586"], "review_helpful_votes": 0} +{"product_id": "0385303882", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 118084, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0385321414", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} +{"product_id": "0385321414", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} +{"product_id": "0399231420", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hope Was Here (Newbery Honor Book)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 73119, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0698118286", "037582233X", "0060535431", "014131088X", "0385730586"], "review_helpful_votes": 0} +{"product_id": "0439064864", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0439064864", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0439064872", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 3807, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0439139597", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 327, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0439139600", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 404, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0439203538", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter And The Chamber Of Secrets", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 47934, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0590373544", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 734802, "product_subcategory": "Education", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0439420105", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 151045, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "044022750X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Laurel Leaf Books)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 480132, "product_subcategory": "Literature", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0440407532", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 10728, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0814250858", "customer_id": "A52OMVEGK0MZG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Come Back Irish", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1240223, "product_subcategory": "Short Stories", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0440408032", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jim Ugly", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 672547, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0440415861", "0440412439", "0440406145", "0689844565", "0141312300"], "review_helpful_votes": 0} +{"product_id": "0440413729", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Belle Prater's Boy", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 57710, "product_subcategory": "People & Places", "similar_product_ids": ["0440413281", "0590371258", "0064405176", "0440414121", "0374308535"], "review_helpful_votes": 0} +{"product_id": "0440418291", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} +{"product_id": "0440418291", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} +{"product_id": "0553280082", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Too Young to Die", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 369874, "product_subcategory": "Science, Nature & How It Works", "similar_product_ids": ["0553280074", "0553283499", "0553283502", "0553562657", "0553570900"], "review_helpful_votes": 0} +{"product_id": "0553471287", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 443501, "product_subcategory": "Children's Books", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0590213105", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P.s. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445386, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116895", "0698116879"], "review_helpful_votes": 0} +{"product_id": "0590213113", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P.s. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 121794, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116879", "0698116895"], "review_helpful_votes": 0} +{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0613182715", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P. S. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1184225, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116879", "0698116895"], "review_helpful_votes": 0} +{"product_id": "0613287142", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Harry Potter (Hardcover))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 122944, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0671505076", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Baby Sitter Burglaries (Nancy Drew on Campus)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 441596, "product_subcategory": "Literature", "similar_product_ids": ["0671001213", "0671000500", "0671505025", "067100753X", "0671872087"], "review_helpful_votes": 0} +{"product_id": "0671751182", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Second Evil (Fear Street Cheerleaders 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 292550, "product_subcategory": "Literature", "similar_product_ids": ["0671868357", "0671868314", "0671529722", "0671694111", "0671702440"], "review_helpful_votes": 0} +{"product_id": "0679819460", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Kidnapped At Birth? (Marvin Redpost 1, paper)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 40914, "product_subcategory": "Literature", "similar_product_ids": ["0679819479", "0679819487", "0679819495", "067988999X", "0679890009"], "review_helpful_votes": 0} +{"product_id": "0698119517", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hope Was Here (2001 Newbery Honor Book)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 7329, "product_subcategory": "Literature", "similar_product_ids": ["0698118286", "037582233X", "0060535431", "014131088X", "0385730586"], "review_helpful_votes": 0} +{"product_id": "0747545774", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1392295, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0786222735", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Thorndike Press Large Print Young Adult Series)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 260444, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0786229276", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 285760, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0786232196", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Thorndike Press Large Print Young Adult Series)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 506235, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0807275530", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 393142, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281913", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 14389, "product_subcategory": "Children's Books", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0807281948", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1227, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807282588", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 5031, "product_subcategory": "Children's Books", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807282596", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4 Audio CD) (Harry Potter (J.K. Rowling))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 661, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807286001", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 990191, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807286001", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 990191, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "080728601X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1043241, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0833597914", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 1213829, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} +{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0939173352", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets, Braille Edition", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 955327, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} +{"product_id": "0939173379", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 868892, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "1567187250", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Teen Witch", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 34955, "product_subcategory": "Earth-Based Religions", "similar_product_ids": ["087542791X", "1567184243", "0738702250", "0738703192", "1567185541"], "review_helpful_votes": 0} +{"product_id": "1883332648", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 407683, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} +{"product_id": "B00005UT2K", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Soundtracks", "product_sales_rank": 30402, "product_subcategory": "General", "similar_product_ids": ["B00005JKW0", "0446608955", "B0000DG001", "B00005KAVP", "B000089IYW"], "review_helpful_votes": 0} +{"product_id": "0451527747", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Alice's Adventures in Wonderland and Through the Looking Glass", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 3259, "product_subcategory": "World Literature", "similar_product_ids": ["0764587218", "0688166776", "0812523350", "0451527046", "0393048470"], "review_helpful_votes": 6} +{"product_id": "037580207X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Sort of Forever", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 568472, "product_subcategory": "People & Places", "similar_product_ids": ["0141312300", "0689844565", "0440442079", "0590386336", "0689859368"], "review_helpful_votes": 0} +{"product_id": "0380713586", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weasel (Avon Camelot Books (Paperback))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 99122, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0440466334", "0440227534", "0439286069", "0763616052", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0671025589", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weep No More, My Lady", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 41334, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 0} +{"product_id": "0671657348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "WEEP NO MORE MY LADY", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 254198, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 0} +{"product_id": "0786812249", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Raptor", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 202869, "product_subcategory": "Animals", "similar_product_ids": ["0786813091", "0786810998", "0786812257", "0786812265", "0786851511"], "review_helpful_votes": 0} +{"product_id": "0786823747", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Raptor", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 2353001, "product_subcategory": "Animals", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0788719408", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weasel", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 1747024, "product_subcategory": "Children's Books", "similar_product_ids": ["0440466334", "0440227534", "0439286069", "0763616052", "0440237688"], "review_helpful_votes": 0} +{"product_id": "0140348107", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 92202, "product_subcategory": "Authors & Illustrators, A-Z", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} +{"product_id": "0141311878", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 311083, "product_subcategory": "Literature", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0141312424", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1549, "product_subcategory": "Literature", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} +{"product_id": "0312857055", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 35312, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} +{"product_id": "0345008634", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (Lord of the Rings (Paperback))", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 302864, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0345339711", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106662, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "037540872X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember (Random House Large Print)", "review_rating": 5, "product_category": "Large Print", "product_sales_rank": 188319, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "0375728007", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Large Print", "product_sales_rank": 42715, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "0385470819", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 19196, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} +{"product_id": "0395489334", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 187772, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0395732611", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1432267, "product_subcategory": "Literature", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0439221684", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Cry of the Wolf (Avalon, 3)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 620441, "product_subcategory": "Literature", "similar_product_ids": ["0439221706", "0439221714", "0439221730", "1593150032", "1593150113"], "review_helpful_votes": 1} +{"product_id": "0439244021", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Haunted Summer", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 602772, "product_subcategory": "Literature", "similar_product_ids": ["0590436031", "0590436023", "0823405818", "0590434616", "0590029533"], "review_helpful_votes": 1} +{"product_id": "0440211727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 4452, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} +{"product_id": "0446525537", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 12303, "product_subcategory": "General", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "0446608955", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 975, "product_subcategory": "Genre Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "0525463461", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 222791, "product_subcategory": "Literature", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} +{"product_id": "0553470876", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 329688, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "0553502220", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 287390, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} +{"product_id": "0553712640", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 406846, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} +{"product_id": "0590065718", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 282224, "product_subcategory": "Education", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} +{"product_id": "0590389246", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 601085, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "0613281292", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 426989, "product_subcategory": "General", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "0618002235", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 52599, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0618037667", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings (Millennium Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 490274, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} +{"product_id": "0618129081", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 809730, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0618153969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 303145, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} +{"product_id": "0618153977", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 351854, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} +{"product_id": "0618153993", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 803279, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0618260293", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 397199, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} +{"product_id": "0618260595", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 243657, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0689808828", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 31079, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "0689826990", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 919, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "0689840926", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 158085, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "0765300273", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 357714, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} +{"product_id": "0765346524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword Of Truth)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 707911, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} +{"product_id": "0671025589", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Weep No More, My Lady", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 41334, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 1} +{"product_id": "0788789546", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Book 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 37606, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "078878983X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Book 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 10518, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0812548051", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 12470, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} +{"product_id": "0828810761", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Le Seigneur des Anneaux, Volume 2", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1471165, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "0833508326", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 259781, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} +{"product_id": "1561005983", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Bookcassette(r) Edition)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 497513, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} +{"product_id": "1565116682", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (Lord of the Rings Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 227237, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} +{"product_id": "1570427496", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 176610, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} +{"product_id": "1581180551", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet (Large Print Cornerstone Ser)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 2074340, "product_subcategory": "Literature & Fiction", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B000001ALS", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Emperors of Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 6457, "product_subcategory": "Classic R&B", "similar_product_ids": ["B000001AKK", "B000001A8J", "B00005NSXV", "B00001QGU7", "0815412185"], "review_helpful_votes": 1} +{"product_id": "B00006FD9K", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Godzilla, King of the Monsters", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 13133, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B00006FD9L", "B00006FD9H", "B00003IXDZ", "B00006FD9G", "B00006FD9I"], "review_helpful_votes": 1} +{"product_id": "B00006FDEB", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Godzilla, King of the Monsters", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23813, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B00006FD9H", "B00006FD9L", "B00003IXDZ", "B00006FD9G", "B00006FD9I"], "review_helpful_votes": 1} +{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} +{"product_id": "B00004STPK", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Infest", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 4076, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B000066S03", "B0002TLJEK", "B00000JCB2", "B0002A2VS2", "B00004R7NE"], "review_helpful_votes": 0} +{"product_id": "0440917409", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Deathwatch (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 43345, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0767902459", "0679853065", "0385038283", "0440945151", "0064405648"], "review_helpful_votes": 1} +{"product_id": "0689822294", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Heaven (Coretta Scott King Author Award Winner)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 195922, "product_subcategory": "People & Places", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} +{"product_id": "0689822901", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "HEAVEN", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 68669, "product_subcategory": "People & Places", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} +{"product_id": "0788745638", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Heaven", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 2152840, "product_subcategory": "Children's Books", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} +{"product_id": "6304507348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Blob", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 2991, "product_subcategory": "General", "similar_product_ids": ["0782009980", "B000067FP3", "B0002V7O0Q", "B000063UR0", "B00009NHC0"], "review_helpful_votes": 1} +{"product_id": "B00004W3HE", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Blob - Criterion Collection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 6611, "product_subcategory": "General", "similar_product_ids": ["0782009980", "B000067FP3", "B0002V7O0Q", "B000063UR0", "B00004RF9B"], "review_helpful_votes": 1} +{"product_id": "0316606103", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Cirque Du Freak #2", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 112022, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} +{"product_id": "0316606847", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Vampire's Assistant (Cirque du Freak, Book 2)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 81251, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} +{"product_id": "0590434616", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Dollhouse Murders (Apple Chillers)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 63506, "product_subcategory": "Literature", "similar_product_ids": ["0380704420", "0590436031", "0823405818", "0380708655", "0590337041"], "review_helpful_votes": 2} +{"product_id": "0786237341", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Cirque Du Freak", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1481041, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} +{"product_id": "B00006LPHA", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Halloween - Resurrection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 10698, "product_subcategory": "General", "similar_product_ids": ["6305291446", "B00004Y632", "B00005OKQF", "6305971099", "B00005LC4Q"], "review_helpful_votes": 0} +{"product_id": "0671657348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "WEEP NO MORE MY LADY", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 254198, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 1} +{"product_id": "0064400670", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Pilot Down, Presumed Dead (Harper Trophy Books (Paperback))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 694441, "product_subcategory": "Literature", "similar_product_ids": ["0064410137", "0064410145"], "review_helpful_votes": 2} +{"product_id": "067168390X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 3357, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} +{"product_id": "0684857529", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 401269, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} +{"product_id": "068487122X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 41789, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} +{"product_id": "1590400453", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove Vol. 1", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 148345, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0684853868"], "review_helpful_votes": 2} +{"product_id": "1590400461", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove Vol. 2", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 1011576, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} +{"product_id": "1562477617", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Voices at Whisper Bend (American Girl History Mysteries)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 98930, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["1562477609", "1562477595", "1562477587", "1562477579", "1584850841"], "review_helpful_votes": 3} +{"product_id": "0385322135", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Voice on the Radio", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 562396, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440220653", "0590988492", "0590474782", "0440219817", "0590457403"], "review_helpful_votes": 0} +{"product_id": "0440219779", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Voice on the Radio (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 40838, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440220653", "0590988492", "0590474782", "0440219817", "0590457403"], "review_helpful_votes": 0} +{"product_id": "0448089270", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Secret of Skull Mountain (Hardy Boys (Hardcover))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 238160, "product_subcategory": "Literature", "similar_product_ids": ["0448089297", "0448089262", "0448089289", "0448089300", "0448089254"], "review_helpful_votes": 1} +{"product_id": "0788749722", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 183963, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0788749730", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 291336, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842316752", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind (Left Behind #1)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 403684, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842329110", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 32523, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842329129", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 1388, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842342702", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 353272, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842343237", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 293315, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0842354204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 667272, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} +{"product_id": "0618037667", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings (Millennium Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 490274, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} +{"product_id": "0618153969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 303145, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} +{"product_id": "0618153977", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 351854, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} +{"product_id": "0618260293", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 397199, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} +{"product_id": "0440978505", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Tex", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 35280, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440975344", "0140389660", "0440204798", "014038572X", "0765305631"], "review_helpful_votes": 4} +{"product_id": "0553258524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 367389, "product_subcategory": "Fantasy", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} +{"product_id": "0689860080", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 12604, "product_subcategory": "Literature", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} +{"product_id": "0689860234", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy, Volume 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 591788, "product_subcategory": "Literature", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} +{"product_id": "0881038164", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1294458, "product_subcategory": "Fantasy", "similar_product_ids": [], "review_helpful_votes": 3} +{"product_id": "6305818282", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 17697, "product_subcategory": "10-12 Years", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} +{"product_id": "6305818398", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 7638, "product_subcategory": "7-9 Years", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} +{"product_id": "6305848033", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The 10th Kingdom (Extended Play Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 10414, "product_subcategory": "Adventure", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} +{"product_id": "B0000648XE", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 349, "product_subcategory": "Television", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} +{"product_id": "0440207800", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "They Never Came Home (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 131438, "product_subcategory": "Horror", "similar_product_ids": ["0440201845", "0440983568", "0440972922", "044098324X", "0440213428"], "review_helpful_votes": 1} +{"product_id": "0060809027", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "My Friend Flicka", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 41543, "product_subcategory": "Animals", "similar_product_ids": ["0060809035", "0060809043", "0380810565", "0689714920", "0689714874"], "review_helpful_votes": 8} +{"product_id": "0465091180", "customer_id": "A3UOR2TGAHLVBA", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "We Were Burning ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 678121, "product_subcategory": "General", "similar_product_ids": ["0804821054", "0066621194"], "review_helpful_votes": 0} +{"product_id": "0883686562", "customer_id": "A3UPT0RGXWHALB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Thunder in Paradise", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 763391, "product_subcategory": "Christianity", "similar_product_ids": ["0768420997", "0768421608", "0883686295", "0768421772", "0768421748"], "review_helpful_votes": 4} +{"product_id": "B00005B4GT", "customer_id": "A3UQ7P0LMBGD1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Amnesiac", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 262947, "product_subcategory": "British Alternative", "similar_product_ids": ["B00004XONN", "B000092ZYX", "B000002TQV", "B000002UJQ", "B000002UR7"], "review_helpful_votes": 1} +{"product_id": "B00005B4GU", "customer_id": "A3UQ7P0LMBGD1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Amnesiac", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 1305, "product_subcategory": "British Alternative", "similar_product_ids": ["B00004XONN", "B000092ZYX", "B000002TQV", "B000002UJQ", "B000002UR7"], "review_helpful_votes": 1} +{"product_id": "0735614962", "customer_id": "A3UR8BBCK8AVNM", "review_date": {"$date": 1013644800000}, "review_votes": 19, "product_group": "Book", "product_title": "HIPAA Compliance Solutions", "review_rating": 1, "product_category": "Professional & Technical", "product_sales_rank": 646442, "product_subcategory": "Law", "similar_product_ids": ["B000069F7B", "0735618682", "B00007CI6F"], "review_helpful_votes": 17} +{"product_id": "0842335986", "customer_id": "A3UUSIYN1MR5WJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unspoken (Lineage of Grace Number 4)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 11978, "product_subcategory": "Fiction", "similar_product_ids": ["0842382658", "1576738167", "0842339523", "0842335714", "0842335684"], "review_helpful_votes": 2} +{"product_id": "158926083X", "customer_id": "A3UUSIYN1MR5WJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unspoken", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 996024, "product_subcategory": "Fiction", "similar_product_ids": ["1576738167", "0842382658", "0842339523", "0842335714", "0842335684"], "review_helpful_votes": 2} +{"product_id": "B00005NNP8", "customer_id": "A3V4CL53QT9X7N", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Music", "product_title": "Barking at Airplanes [Bonus Tracks]", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 23504, "product_subcategory": "Pop Rock", "similar_product_ids": ["B00005NNP9", "B00005NVYE", "B000085RRG", "B00000IAZR", "B000008E14"], "review_helpful_votes": 10} +{"product_id": "0884196755", "customer_id": "A3V4X90KKFW9WU", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Prophetic Etiquette", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 454831, "product_subcategory": "Christianity", "similar_product_ids": ["0884194264", "0768422329", "0800793269", "0830733892", "0310225582"], "review_helpful_votes": 7} +{"product_id": "0412808307", "customer_id": "A3V8W69FK0918O", "review_date": {"$date": 1013644800000}, "review_votes": 19, "product_group": "Book", "product_title": "Introduction to Mathematical Logic, Fourth Edition", "review_rating": 5, "product_category": "Science", "product_sales_rank": 55310, "product_subcategory": "Mathematics", "similar_product_ids": ["0521007585", "0691029067", "0486434753", "0486425339", "0486634620"], "review_helpful_votes": 15} +{"product_id": "B00005U15M", "customer_id": "A3VAD7YDFFQOO5", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Roger Waters - In the Flesh (Live)", "review_rating": 3, "product_category": "Music Video & Concerts", "product_sales_rank": 36424, "product_subcategory": "General", "similar_product_ids": ["B00006LI4S", "B00009VTYE", "B0000DBJDM", "B0000AOV85", "B0000027I6"], "review_helpful_votes": 1} +{"product_id": "B00005U122", "customer_id": "A3VAD7YDFFQOO5", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "Roger Waters - In the Flesh (Live)", "review_rating": 3, "product_category": "Music Video & Concerts", "product_sales_rank": 3272, "product_subcategory": "General", "similar_product_ids": ["B00006LI4S", "B00009VTYE", "B0000DBJDM", "B0000AOV85", "B0000027I6"], "review_helpful_votes": 1} +{"product_id": "B00005MKTL", "customer_id": "A3VC1M1X0U31N", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Global Underground 21 - Moscow", "review_rating": 2, "product_category": "Indie Music", "product_sales_rank": 43727, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B000095J7T", "B000095J7P", "B00003GNZH", "B00005LN1Y", "B00009Y3QU"], "review_helpful_votes": 2} +{"product_id": "B00005NZK5", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Last Man on Earth", "review_rating": 4, "product_category": "Indie Music", "product_sales_rank": 55129, "product_subcategory": "Folk", "similar_product_ids": ["B0000AKCMI", "B000002US4", "B000006035", "B0007Z9R7U", "B0000004VE"], "review_helpful_votes": 4} +{"product_id": "0745128319", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Blood Sport", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 1027880, "product_subcategory": "Mystery", "similar_product_ids": ["0449221121", "0515125601", "0515124451", "044922113X", "0449221148"], "review_helpful_votes": 5} +{"product_id": "0679735771", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "American Psycho (Vintage Contemporaries)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1301, "product_subcategory": "United States", "similar_product_ids": ["067978148X", "0679781498", "0375703845", "0805076476", "0679743243"], "review_helpful_votes": 0} +{"product_id": "0679735771", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "American Psycho (Vintage Contemporaries)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1301, "product_subcategory": "United States", "similar_product_ids": ["067978148X", "0679781498", "0375703845", "0805076476", "0679743243"], "review_helpful_votes": 0} +{"product_id": "0915297019", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Once a Runner", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 4100, "product_subcategory": "Individual Sports", "similar_product_ids": ["1585743283", "1891369504", "0618391126", "0790739291", "0875964575"], "review_helpful_votes": 0} +{"product_id": "B0000025D0", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Music", "product_title": "Darkness on the Edge of Town", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 2593, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B00000255F", "B0000025KI", "B000002513", "B0000024ZT", "B0000025T6"], "review_helpful_votes": 1} +{"product_id": "B0000025T6", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Nebraska", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 1096, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B0007WF1WS", "B000002BFL", "B0000025KI", "B0000025D0", "B00000255F"], "review_helpful_votes": 0} +{"product_id": "B00005UKKE", "customer_id": "A3VHAB1RV9WXLD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Britney Spears - Live from Las Vegas", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 23129, "product_subcategory": "General", "similar_product_ids": ["B000051S4N", "B00064AM62", "B00005RDAF", "B0001BXYUG", "B00002ZMNO"], "review_helpful_votes": 0} +{"product_id": "B00005UKKF", "customer_id": "A3VHAB1RV9WXLD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Britney Spears - Live from Las Vegas", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 3470, "product_subcategory": "General", "similar_product_ids": ["B000051S4N", "B00064AM62", "B00005RDAF", "B0001BXYUG", "B00002ZMNO"], "review_helpful_votes": 0} +{"product_id": "0783221487", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Dune (Widescreen Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 26397, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} +{"product_id": "0783226063", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Dune", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 9170, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} +{"product_id": "6300183971", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Dune", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 6737, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} +{"product_id": "0312284330", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 271207, "product_subcategory": "Government", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} +{"product_id": "0312302584", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 32795, "product_subcategory": "Government", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} +{"product_id": "B00008RUNJ", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "", "product_sales_rank": 265588, "product_subcategory": "", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} +{"product_id": "B00000JZC4", "customer_id": "A3VMFN7X82SK5N", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Title of Record", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 11860, "product_subcategory": "General", "similar_product_ids": ["B000002MX5", "B00006916E", "B000009OPW", "B00000IP2T", "B000005ZD3"], "review_helpful_votes": 0} +{"product_id": "6300216802", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Star Trek - The Motion Picture", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23275, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} +{"product_id": "B00005JKHP", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Star Trek - The Motion Picture (The Director's Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2762, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} +{"product_id": "B00005OLAS", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Star Trek - The Motion Picture (The Director's Edition) (Widescreen)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 8926, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} +{"product_id": "0807847445", "customer_id": "A3VRBXK9HL8W1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Genius of Alexander the Great", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 200965, "product_subcategory": "General", "similar_product_ids": ["0520071662", "0143035134", "0140442537", "1592400531", "0140444122"], "review_helpful_votes": 1} +{"product_id": "0807847445", "customer_id": "A3VRBXK9HL8W1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Genius of Alexander the Great", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 200965, "product_subcategory": "General", "similar_product_ids": ["0520071662", "0143035134", "0140442537", "1592400531", "0140444122"], "review_helpful_votes": 1} +{"product_id": "0786607815", "customer_id": "A3VT1HNJOZ33VM", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Learning the Tabla Book/CD Set", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 38668, "product_subcategory": "Music", "similar_product_ids": ["0964369427", "0963444794", "B000009HRR", "B00005092C", "B00005092O"], "review_helpful_votes": 17} +{"product_id": "0967303524", "customer_id": "A3VZZGNL13I1NR", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Alice at Heart (Waterlilies Series)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 403337, "product_subcategory": "General", "similar_product_ids": ["0967303575", "0446614793", "0425189163", "0446611409", "0446610674"], "review_helpful_votes": 1} +{"product_id": "0803960522", "customer_id": "A3W0IQ8GCH79IE", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Path to School Leadership ", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 416529, "product_subcategory": "Education", "similar_product_ids": ["141290496X", "0761946071"], "review_helpful_votes": 0} +{"product_id": "0971007829", "customer_id": "A3W39HBAEWHRZ8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Microbranding", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 104209, "product_subcategory": "Economics", "similar_product_ids": ["0446394688", "0814479863", "0793176816", "0385504454", "0814470726"], "review_helpful_votes": 2} +{"product_id": "B00004TH83", "customer_id": "A3X0T82Q0LLDQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Lara Fabian", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 11341, "product_subcategory": "General", "similar_product_ids": ["B000244NK2", "B00004S7L3", "B0000BXGCN", "B00000I2LB", "B00005NW83"], "review_helpful_votes": 3} +{"product_id": "B00004TH84", "customer_id": "A3X0T82Q0LLDQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Lara Fabian [2000]", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 404797, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 3} +{"product_id": "B0000509C4", "customer_id": "A42J5VDT7MHOM", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Creepshow 2", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9668, "product_subcategory": "General", "similar_product_ids": ["0790744295", "B00005NG6B", "B00006FDCU", "6305972591", "B00004W5UF"], "review_helpful_votes": 1} +{"product_id": "B000059PRW", "customer_id": "A42J5VDT7MHOM", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Creepshow 2", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 35725, "product_subcategory": "General", "similar_product_ids": ["0790744295", "B00005NG6B", "B00006FDCU", "6305972591", "B00004W5UF"], "review_helpful_votes": 1} +{"product_id": "B000000DDJ", "customer_id": "A43756YCL2QPL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "21 Hits Special Collection", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 160377, "product_subcategory": "Pop Rock", "similar_product_ids": ["B000000D5Z"], "review_helpful_votes": 0} +{"product_id": "6303168507", "customer_id": "A46NPO3VKOZPJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Schindler's List", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 6967, "product_subcategory": "General", "similar_product_ids": ["B0001NBLVI", "B00005JLT5", "B00028HBKM", "B00003CXCT", "B00003CXA2"], "review_helpful_votes": 1} +{"product_id": "0786708468", "customer_id": "A474FI652OHNI", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Well", "review_rating": 4, "product_category": "Computers & Internet", "product_sales_rank": 646787, "product_subcategory": "Digital Business & Culture", "similar_product_ids": ["0684832674", "0735710759", "0684833484", "0670033820", "0596007191"], "review_helpful_votes": 1} +{"product_id": "0451200438", "customer_id": "A47WXMWXCOGXQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Panic Attack Recovery Book", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 219828, "product_subcategory": "Self-Help", "similar_product_ids": ["0060951605", "0449213315", "0060927585", "089486971X", "0809231026"], "review_helpful_votes": 3} +{"product_id": "0786861037", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Five Equations That Changed the World", "review_rating": 4, "product_category": "Science", "product_sales_rank": 453118, "product_subcategory": "History & Philosophy", "similar_product_ids": ["0785260242", "0874772338", "0486289737", "0385490623", "0195129113"], "review_helpful_votes": 14} +{"product_id": "0786881879", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Five Equations That Changed the World ", "review_rating": 4, "product_category": "Science", "product_sales_rank": 110981, "product_subcategory": "History & Philosophy", "similar_product_ids": ["0785260242", "0874772338", "0486289737", "0385490623", "0195129113"], "review_helpful_votes": 14} +{"product_id": "0486661652", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Theory and Application of Infinite Series", "review_rating": 4, "product_category": "Science", "product_sales_rank": 48788, "product_subcategory": "Mathematics", "similar_product_ids": ["0486601536", "0486692191", "0486428753", "0521358809", "082182693X"], "review_helpful_votes": 6} +{"product_id": "038550120X", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 111260, "product_subcategory": "General", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} +{"product_id": "044023722X", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 1842, "product_subcategory": "Thrillers", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} +{"product_id": "0553502751", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 217167, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} +{"product_id": "0553712527", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 301752, "product_subcategory": "General", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} +{"product_id": "B000058DX3", "customer_id": "A4HYUXRZKM33V", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Things We Lost in the Fire", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 27504, "product_subcategory": "General", "similar_product_ids": ["B00006JJ48", "B000777J9G", "B00000IAD0", "B000000A3W", "B000000A42"], "review_helpful_votes": 2} +{"product_id": "B00000JO1Z", "customer_id": "A4SAI3HDIK3UI", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Globe Sessions", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 19725, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B000002G62", "B0000636UN", "B000002G1T", "B00003L4DJ", "B0000DZ3E2"], "review_helpful_votes": 0} +{"product_id": "0814250858", "customer_id": "A52OMVEGK0MZG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Come Back Irish", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1240223, "product_subcategory": "Short Stories", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "0446678430", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 1490, "product_subcategory": "Industries & Professions", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} +{"product_id": "1586212559", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich ", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 298115, "product_subcategory": "Personal Finance", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} +{"product_id": "1586212567", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich ", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 31034, "product_subcategory": "Personal Finance", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} +{"product_id": "B00005QD97", "customer_id": "A53VUA1WE6N7I", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Punkzilla", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 108637, "product_subcategory": "General", "similar_product_ids": ["B0000007QS", "B00003TFUH", "B000009CD0", "B000003J1W", "B00005JIYC"], "review_helpful_votes": 1} +{"product_id": "0875420281", "customer_id": "A5427Y1D10XM0", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Animal-Speak", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 2217, "product_subcategory": "Earth-Based Religions", "similar_product_ids": ["1888767340", "1888767480", "0312204914", "0875420087", "1888767057"], "review_helpful_votes": 15} +{"product_id": "0971260109", "customer_id": "A56LLILL8LK4K", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "This is NOT Brain Surgery! A Mental Health Companion for the Gastric Bypass Patient", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 822230, "product_subcategory": "Mental Health", "similar_product_ids": [], "review_helpful_votes": 4} +{"product_id": "0345413881", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death (Alex Delaware)", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 18042, "product_subcategory": "Police Procedurals", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} +{"product_id": "0679459618", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death ", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 326385, "product_subcategory": "Police Procedurals", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} +{"product_id": "B00007D040", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 119528, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} +{"product_id": "0140707018", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (New Penguin Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 527022, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} +{"product_id": "0140714847", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (The Pelican Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 258951, "product_subcategory": "World Literature", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0174436041", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1077810, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0451526864", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Tragedy of Romeo and Juliet (Signet Classic, 2686)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 87072, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0460871773", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Everyman's Library (Paper))", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1132378, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "B00005PJ8E", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Quills", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 20748, "product_subcategory": "Period Piece", "similar_product_ids": ["B00003CWRC", "B000056BSF", "B00007AJFB", "B0000E32V0", "076781777X"], "review_helpful_votes": 2} +{"product_id": "0521294053", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (The New Cambridge Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1217567, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0521634970", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Cambridge School Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 110729, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0553213059", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Bantam Classic)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 350348, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} +{"product_id": "0671722859", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "ROMEO AND JULIET", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 238088, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} +{"product_id": "089845980X", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 454364, "product_subcategory": "World Literature", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} +{"product_id": "B00005UPFI", "customer_id": "A5GJXZCBM6F3G", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Music", "product_title": "Greatest Love Songs", "review_rating": 4, "product_category": "Pop", "product_sales_rank": 4372, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B00007LTI5", "B000002NFI", "B0000479AV", "B000002LOI", "B000002AJH"], "review_helpful_votes": 8} +{"product_id": "0312181531", "customer_id": "A5GMDKHEW3R9F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "An Original Man ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 55620, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0875524745", "067944260X", "1884855237", "1884855210", "188485513X"], "review_helpful_votes": 1} +{"product_id": "0609808052", "customer_id": "A5GRFTMJYEHYP", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Tagbook ", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 955586, "product_subcategory": "Social Sciences", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "6305428220", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Faculty", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 2156, "product_subcategory": "General", "similar_product_ids": ["0792840127", "0780631684", "B00004W20F", "B0006J28KK", "B00002RB4P"], "review_helpful_votes": 1} +{"product_id": "B00000IO4J", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "The Faculty", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 15606, "product_subcategory": "General", "similar_product_ids": ["0792840127", "0780631684", "B00004W20F", "B0006J28KK", "B00002RB4P"], "review_helpful_votes": 1} +{"product_id": "0790731916", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Forever Young", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 5606, "product_subcategory": "General", "similar_product_ids": ["B00019073K", "0790731940", "6304708793", "0783233507", "0783227396"], "review_helpful_votes": 1} +{"product_id": "079074015X", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Forever Young", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 12625, "product_subcategory": "General", "similar_product_ids": ["B00019073K", "0790731940", "0783233507", "6304708793", "0783227396"], "review_helpful_votes": 1} +{"product_id": "6305219931", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Forever Young", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 101058, "product_subcategory": "Fantasy", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "630300203X", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The Good Son", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 16175, "product_subcategory": "Suspense", "similar_product_ids": ["0783233507", "B0002TSZI8", "B0001I55V0", "B0000VV512", "B00005TPMM"], "review_helpful_votes": 5} +{"product_id": "0375501932", "customer_id": "A5KB7UIU6ZUL6", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Nancy Silverton's Pastries from the La Brea Bakery", "review_rating": 1, "product_category": "Cooking, Food & Wine", "product_sales_rank": 39306, "product_subcategory": "Baking", "similar_product_ids": ["0679409076", "0375412603", "0618138927", "0061817708", "0517224909"], "review_helpful_votes": 3} +{"product_id": "0679409076", "customer_id": "A5KB7UIU6ZUL6", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Nancy Silverton's Breads from the La Brea Bakery ", "review_rating": 1, "product_category": "Cooking, Food & Wine", "product_sales_rank": 39814, "product_subcategory": "Baking", "similar_product_ids": ["0375501932", "1580082688", "1580080030", "0898159164", "1579651178"], "review_helpful_votes": 2} +{"product_id": "B000001I0E", "customer_id": "A5KJVGJ43ZDC9", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Bad Music for Bad People", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 17062, "product_subcategory": "General", "similar_product_ids": ["B000001I0K", "B00005O7W8", "B000001I09", "B000002L31", "B00005O7W6"], "review_helpful_votes": 2} +{"product_id": "0060007834", "customer_id": "A5MPR38KL612P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unnatural Fire ", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 514607, "product_subcategory": "Mystery", "similar_product_ids": ["0060522062", "0375508554", "075284475X", "0340793325", "081257236X"], "review_helpful_votes": 2} +{"product_id": "0688176836", "customer_id": "A5MPR38KL612P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unnatural Fire", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 630471, "product_subcategory": "Mystery", "similar_product_ids": ["0060522062", "0375508554", "075284475X", "0340793325", "081257236X"], "review_helpful_votes": 2} +{"product_id": "B000002564", "customer_id": "A5PP5IRQDVZSG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Silk Degrees", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 1975, "product_subcategory": "Soft Rock", "similar_product_ids": ["B00000252C", "B0000025KC", "B0000025A2", "B000089HC7", "B00000DCGY"], "review_helpful_votes": 1} +{"product_id": "B00005QG8W", "customer_id": "A61CGWLOIZJ7V", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Fake Sound of Progress", "review_rating": 5, "product_category": "Folk", "product_sales_rank": 21319, "product_subcategory": "Traditional British & Celtic Folk", "similar_product_ids": ["B00019PD0W", "B0000C23D6", "B0002A2VS2", "B0000A0WKG", "B00006GF9L"], "review_helpful_votes": 0} +{"product_id": "0671318489", "customer_id": "A61VICZMFN9RU", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Shiva Option", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 338568, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0671877798", "0671720244", "0671721119", "0743488520", "074349881X"], "review_helpful_votes": 2} +{"product_id": "B000003BEU", "customer_id": "A62FJDQG6SJNL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Their Satanic Majesties Request", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 446718, "product_subcategory": "Supergroups", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "B000003BEV", "customer_id": "A62FJDQG6SJNL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Satanic Majesties Request", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 27458, "product_subcategory": "Psychedelic Rock", "similar_product_ids": ["B000003BEM", "B000003BEG", "B000003BDY", "B000003BEA", "B00006AW2T"], "review_helpful_votes": 0} +{"product_id": "0671316486", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In The Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 140220, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} +{"product_id": "0671582828", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In The Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 191127, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} +{"product_id": "0684841363", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "IN THE MEANTIME ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 57125, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} +{"product_id": "0684848066", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In the Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 3096, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} +{"product_id": "068487072X", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In the Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 1122795, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} +{"product_id": "B00004TX01", "customer_id": "A6EKTPVKZ41DJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Caged Combat - Kiev, Ukraine", "review_rating": 4, "product_category": "Sports", "product_sales_rank": 49783, "product_subcategory": "Wrestling", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0252067959", "customer_id": "A6G57DQXL28RQ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Cyber-Marx", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 557473, "product_subcategory": "Economics", "similar_product_ids": ["1583670882", "1594200246", "1859843301", "0745316069", "0262692333"], "review_helpful_votes": 5} +{"product_id": "0873891511", "customer_id": "A6J9LEDY715BA", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Creating a Customer-Centered Culture", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 282962, "product_subcategory": "General", "similar_product_ids": ["0201608138", "0201154935", "1563273012", "0972572805", "1578512549"], "review_helpful_votes": 1} +{"product_id": "1861542119", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Jam", "review_rating": 2, "product_category": "Arts & Photography", "product_sales_rank": 149197, "product_subcategory": "Graphic Design", "similar_product_ids": ["1895497493", "081184255X", "3775712542", "1891024604", "0810967022"], "review_helpful_votes": 6} +{"product_id": "0821224638", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "The Essential Duane Michals", "review_rating": 3, "product_category": "Arts & Photography", "product_sales_rank": 448609, "product_subcategory": "Photography", "similar_product_ids": ["0944092861", "1900564734", "0944092349", "1931788340", "082122459X"], "review_helpful_votes": 1} +{"product_id": "0802137598", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Pocket Canons 10-copy Boxed Set", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 366526, "product_subcategory": "Christianity", "similar_product_ids": ["0192834118", "0802136095"], "review_helpful_votes": 1} +{"product_id": "0714834831", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Michelangelo (art and ideas)", "review_rating": 5, "product_category": "Arts & Photography", "product_sales_rank": 367257, "product_subcategory": "Art", "similar_product_ids": ["019283410X", "0192837702", "0812091752", "0812094263", "0812019997"], "review_helpful_votes": 3} +{"product_id": "B000002BHE", "customer_id": "A6P74FB5ZXMW8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Music", "product_title": "Falling into You", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 3034, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B000002C4J", "B0000029DQ", "B000031XCR", "B00005YXZI", "B0000028M4"], "review_helpful_votes": 3} +{"product_id": "0767002652", "customer_id": "A6QA74AASV8RM", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Upstairs Downstairs - The Premiere Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 4869, "product_subcategory": "TV Series", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 3} +{"product_id": "B00005NKCM", "customer_id": "A6QA74AASV8RM", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Upstairs Downstairs - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 5806, "product_subcategory": "A&E Home Video", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 3} +{"product_id": "B000002HMH", "customer_id": "A6RK21XAAVHJ5", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Load", "review_rating": 2, "product_category": "Hard Rock & Metal", "product_sales_rank": 2474, "product_subcategory": "General", "similar_product_ids": ["B000002HRE", "B000002H97", "B000002H33", "B000002H2H", "B000002H6C"], "review_helpful_votes": 3} +{"product_id": "B000025JVE", "customer_id": "A6RK21XAAVHJ5", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Victims of the Future", "review_rating": 4, "product_category": "Classic Rock", "product_sales_rank": 65235, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": [], "review_helpful_votes": 0} +{"product_id": "0735201609", "customer_id": "A6SHVHC69ERT2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "How to Make Million$ in Real Estate in Three Years Startingwith No Cash, Third Edition", "review_rating": 2, "product_category": "Business & Investing", "product_sales_rank": 36595, "product_subcategory": "General", "similar_product_ids": ["0735201161", "0471464996", "0793173655", "0793144914", "0071373373"], "review_helpful_votes": 2} +{"product_id": "B00005RFAI", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Missundaztood", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 2800, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "B00005RGI0", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 242158, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "B00005UW47", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood [German Bonus Track]", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 112988, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "193184125X", "customer_id": "A7974HWVHZMNH", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Visual Basic Game Programming with DirectX (The Premier Press Game Development Series)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 188449, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["0789725924", "0672322250", "0471355992", "1592000096", "1590594010"], "review_helpful_votes": 2} +{"product_id": "B00003CXI0", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 280, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B00003CXI1", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Special Widescreen Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 337, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B000062TU1", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Full Screen Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 1576, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B000062TU2", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone - Spanish Edition", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4207, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B00006IRHA", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 40700, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B00006IRHB", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 33519, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} +{"product_id": "B00003CXHJ", "customer_id": "A7DPX5TBE8V1O", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "U-571 (Collector's Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 4304, "product_subcategory": "General", "similar_product_ids": ["B00005JLGJ", "0767802470", "B00008K76U", "6304765258", "B00003CXRA"], "review_helpful_votes": 4} +{"product_id": "B00005B6N7", "customer_id": "A7DPX5TBE8V1O", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Video", "product_title": "U-571", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 10126, "product_subcategory": "General", "similar_product_ids": ["B00005JLGJ", "0767802470", "B00008K76U", "6304765258", "B00003CXRA"], "review_helpful_votes": 4} +{"product_id": "B00004WKDD", "customer_id": "A7EAZIPQAVNYZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Mechmetio", "review_rating": 5, "product_category": "International", "product_sales_rank": 31228, "product_subcategory": "Europe", "similar_product_ids": ["B000005IZA", "B00004YL4I", "B0000034AU", "B000005IW5", "B00005R1PX"], "review_helpful_votes": 0} +{"product_id": "0830813241", "customer_id": "A7EE5ZR41SX5O", "review_date": {"$date": 1013644800000}, "review_votes": 25, "product_group": "Book", "product_title": "Darwin on Trial", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 33339, "product_subcategory": "Christianity", "similar_product_ids": ["0684834936", "0830813608", "091756152X", "0895262002", "0830819290"], "review_helpful_votes": 14} +{"product_id": "6303695779", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Vampyr", "review_rating": 1, "product_category": "Art House & International", "product_sales_rank": 41791, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005O5CA", "0780022343", "B00005M2C7", "6305075492", "B0002NRS46"], "review_helpful_votes": 1} +{"product_id": "6305078491", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Vampyr", "review_rating": 1, "product_category": "Art House & International", "product_sales_rank": 25577, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005O5CA", "0780022343", "B00005M2C7", "6305075492", "B0002NRS46"], "review_helpful_votes": 1} +{"product_id": "B0000029K1", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "A Gene Autry Christmas", "review_rating": 3, "product_category": "Country", "product_sales_rank": 187588, "product_subcategory": "Cowboy", "similar_product_ids": [], "review_helpful_votes": 2} +{"product_id": "B000053V8F", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Frank Herbert's Dune (TV Miniseries)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 24691, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} +{"product_id": "B00005O5BA", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Frank Herbert's Dune (TV Miniseries)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 32035, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} +{"product_id": "B00005O5H0", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Frank Herbert's Dune (TV Miniseries) (EP Version)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 13897, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441172717"], "review_helpful_votes": 0} +{"product_id": "B0000639EV", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Frank Herbert's Dune (TV Miniseries) (Director's Cut Special Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1323, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} +{"product_id": "B00005R87Q", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "The Fast and the Furious", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 3417, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00008EYA5"], "review_helpful_votes": 0} +{"product_id": "B000063USY", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "The Fast and the Furious", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 14370, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00008EYA5"], "review_helpful_votes": 0} +{"product_id": "B00008MZ0N", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "The Fast and the Furious (Widescreen Tricked Out Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 4968, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00007LB4C"], "review_helpful_votes": 0} +{"product_id": "0764550381", "customer_id": "A7W44JUDEZC44", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "House Selling for Dummies", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 168383, "product_subcategory": "General", "similar_product_ids": ["0764553313", "0609809334", "0793150264", "0517888440", "097073462X"], "review_helpful_votes": 19} +{"product_id": "0764554255", "customer_id": "A7W44JUDEZC44", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "House Selling for Dummies", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 6220, "product_subcategory": "General", "similar_product_ids": ["0764553313", "0609809334", "0793150264", "0517888440", "097073462X"], "review_helpful_votes": 19} +{"product_id": "0786862181", "customer_id": "A817ZFWX0NMXC", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Surrendering to Marriage", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 309264, "product_subcategory": "Social Sciences", "similar_product_ids": ["0786869135", "0786883189", "0312254709", "0767900421", "0743210808"], "review_helpful_votes": 6} +{"product_id": "0786887710", "customer_id": "A817ZFWX0NMXC", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Surrendering to Marriage ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 172900, "product_subcategory": "Relationships", "similar_product_ids": ["0786869135", "0786883189", "0312254709", "0767900421", "0743210808"], "review_helpful_votes": 6} +{"product_id": "B000053VB4", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "DVD", "product_title": "Mystic Pizza", "review_rating": 1, "product_category": "Drama", "product_sales_rank": 5388, "product_subcategory": "General", "similar_product_ids": ["6305696071", "B00002ND7J", "B00003CXFV", "B00004TJKK", "0767821769"], "review_helpful_votes": 4} +{"product_id": "B000053VDQ", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Video", "product_title": "Mystic Pizza", "review_rating": 1, "product_category": "Drama", "product_sales_rank": 5474, "product_subcategory": "General", "similar_product_ids": ["6305696071", "B00002ND7J", "B00003CXFV", "B00004TJKK", "0767821769"], "review_helpful_votes": 4} +{"product_id": "6303675034", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Pump up the Volume", "review_rating": 2, "product_category": "Drama", "product_sales_rank": 16171, "product_subcategory": "General", "similar_product_ids": ["B000059PPG", "B00009AOBM", "B000002O8M", "B00006FDCF", "B00003CXCI"], "review_helpful_votes": 6} +{"product_id": "B000031EG0", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "DVD", "product_title": "Pump up the Volume", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 6630, "product_subcategory": "By Country", "similar_product_ids": ["B000059PPG", "B00009AOBM", "B000002O8M", "B00006FDCF", "B00003CXCI"], "review_helpful_votes": 6} +{"product_id": "B00003CXPV", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Quills", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 7892, "product_subcategory": "General", "similar_product_ids": ["B00003CWRC", "B000056BSF", "B00007AJFB", "B0000E32V0", "076781777X"], "review_helpful_votes": 2} +{"product_id": "B00005Q6NP", "customer_id": "A8BROR21R5NPM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Innocence & Despair", "review_rating": 3, "product_category": "Indie Music", "product_sales_rank": 39804, "product_subcategory": "Miscellaneous", "similar_product_ids": ["B00006NSX1", "B000087DRX", "B000077SX3", "1556523726", "B000003F97"], "review_helpful_votes": 3} +{"product_id": "0786915528", "customer_id": "A8IZXBE7J6RNJ", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Monster Manual", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 15172, "product_subcategory": "Fantasy", "similar_product_ids": ["078691551X", "0786915501", "0786918454", "0786926538", "0786928735"], "review_helpful_votes": 2} +{"product_id": "B00005UT2K", "customer_id": "A8OAEO4POY0JN", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Soundtracks", "product_sales_rank": 30402, "product_subcategory": "General", "similar_product_ids": ["B00005JKW0", "0446608955", "B0000DG001", "B00005KAVP", "B000089IYW"], "review_helpful_votes": 0} +{"product_id": "1892890062", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Beauty of Horses - Horse Lover's Library, Vol. 1 (Screen-A-Day-Calendar) (60-Second Smart)", "review_rating": 3, "product_category": "Calendars", "product_sales_rank": 1453843, "product_subcategory": "Block Calendars", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "043936213X", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "0590353403", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "0786222727", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "0807281751", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "0807281956", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "0939173344", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} +{"product_id": "B000001DYA", "customer_id": "A8OQZV538BU1Y", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Vincebus Eruptum", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 33775, "product_subcategory": "Psychedelic Rock", "similar_product_ids": ["B000001DY9", "B000005IS1", "B000003CMR", "B00004WGY4", "B000002IAK"], "review_helpful_votes": 2} +{"product_id": "B000002UJQ", "customer_id": "A8RQSDCLE1JF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Ok Computer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 160, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002TQV", "B00004XONN", "B000092ZYX", "B00005B4GU", "B000002UR7"], "review_helpful_votes": 1} +{"product_id": "B000002UJR", "customer_id": "A8RQSDCLE1JF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "OK Computer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 228214, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002TQV", "B00004XONN", "B000092ZYX", "B00005B4GU", "B000002UR7"], "review_helpful_votes": 1} +{"product_id": "6304711921", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Nightmare Before Christmas", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 41051, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} +{"product_id": "6305949972", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "The Nightmare Before Christmas - Special Edition (Widescreen)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 7112, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} +{"product_id": "6305949980", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Nightmare Before Christmas (Special Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 443, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} +{"product_id": "B00005UDE3", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Music", "product_title": "Big Generator", "review_rating": 4, "product_category": "Rock", "product_sales_rank": 231090, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B00005B19Z", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "More You Know", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 323171, "product_subcategory": "Rock", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B00005NWMK", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Magnification", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 72433, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B00001O2V8", "B000069KGN", "B000005CG0", "B000001Y9T", "B00005YUNY"], "review_helpful_votes": 1} +{"product_id": "B000066I3R", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Magnification", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 156115, "product_subcategory": "Progressive", "similar_product_ids": ["B00001O2V8", "B000069KGN", "B000005CG0", "B00005YUNY", "B000001Y9T"], "review_helpful_votes": 1} +{"product_id": "031287717X", "customer_id": "A9304G3R4X8LT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Wayfarer Redemption, Book 1", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 387550, "product_subcategory": "Fantasy", "similar_product_ids": ["0765341964", "0765342812", "0312870469", "0732259320", "0765344424"], "review_helpful_votes": 0} +{"product_id": "0765341301", "customer_id": "A9304G3R4X8LT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Wayfarer Redemption (The Axis Trilogy, Bk 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 111008, "product_subcategory": "Fantasy", "similar_product_ids": ["0765341964", "0765342812", "0312870469", "0732259320", "0765344424"], "review_helpful_votes": 0} +{"product_id": "B00004XMSB", "customer_id": "A9B7MPB3BMF8I", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Hercules in New York", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 23503, "product_subcategory": "General", "similar_product_ids": ["B0000C3I6U", "B00013RC8E", "B00018YC3M", "B000063INF", "B0001Z37HM"], "review_helpful_votes": 14} +{"product_id": "B00004XMSC", "customer_id": "A9B7MPB3BMF8I", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "DVD", "product_title": "Hercules in New York", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 7621, "product_subcategory": "General", "similar_product_ids": ["B0000C3I6U", "B00018YC3M", "B00013RC8E", "B000063INF", "B0001Z37HM"], "review_helpful_votes": 14} +{"product_id": "B00005RFAI", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Missundaztood", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 2800, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "B00005RGI0", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 242158, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "B00005UW47", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood [German Bonus Track]", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 112988, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} +{"product_id": "B0000004QS", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Conspiracy No. 5", "review_rating": 5, "product_category": "Christian & Gospel", "product_sales_rank": 26969, "product_subcategory": "Christian Rock", "similar_product_ids": ["B0000004QQ", "B00000JYAC", "B00005OKUS", "B0001Z36VO", "B00004TZBU"], "review_helpful_votes": 2} +{"product_id": "0968621414", "customer_id": "A9KF4UCP7DXLE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Indie Bible", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 692051, "product_subcategory": "Music", "similar_product_ids": [], "review_helpful_votes": 3} +{"product_id": "0968621422", "customer_id": "A9KF4UCP7DXLE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Indie Bible (Indie Bible)", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 492612, "product_subcategory": "Music", "similar_product_ids": [], "review_helpful_votes": 3} +{"product_id": "0671042262", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere ", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 122628, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} +{"product_id": "0684871270", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere ", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 223995, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} +{"product_id": "0743506405", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 781854, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} +{"product_id": "B0000025GR", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Winner Takes All", "review_rating": 4, "product_category": "R&B", "product_sales_rank": 59367, "product_subcategory": "General", "similar_product_ids": ["B00000258G", "B00005NKKR", "B00005NKKS", "B0000025V4", "B000002LBT"], "review_helpful_votes": 2} +{"product_id": "B00005M9B6", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Body & Soul", "review_rating": 4, "product_category": "R&B", "product_sales_rank": 72965, "product_subcategory": "General", "similar_product_ids": ["B00004L8HV", "B00005V8T2", "B00005BC7O", "B000083MCY", "B00000BIL4"], "review_helpful_votes": 1} +{"product_id": "B00000BIL4", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Body & Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 12265, "product_subcategory": "General", "similar_product_ids": ["B00004L8HV", "B00005V8T2", "B00016XN8Y", "B00005BC7O", "B0000931MS"], "review_helpful_votes": 2} +{"product_id": "B000002AA9", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Best of Walter Jackson", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 38822, "product_subcategory": "General", "similar_product_ids": ["B0000008JF", "B00003E435", "B00004SW64", "B00005K9SM", "B00000150B"], "review_helpful_votes": 5} +{"product_id": "B00005RIY5", "customer_id": "A9VU1SKTY5M09", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Queer as Folk - The Complete First Season (Showtime)", "review_rating": 4, "product_category": "Television", "product_sales_rank": 1961, "product_subcategory": "General", "similar_product_ids": ["B0000798EY", "B0000V46D6", "B0007DBJG4", "B0002MPQRS", "B0002I84JO"], "review_helpful_votes": 1} +{"product_id": "B00005RJ22", "customer_id": "A9VU1SKTY5M09", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Queer As Folk - The Complete First Season (Showtime)", "review_rating": 4, "product_category": "Television", "product_sales_rank": 6368, "product_subcategory": "General", "similar_product_ids": ["B0000798EY", "B0000V46D6", "B0007DBJG4", "B0002I84JO", "B0002MPQRS"], "review_helpful_votes": 1} +{"product_id": "0060952709", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "3-Minute Abs", "review_rating": 2, "product_category": "Health, Mind & Body", "product_sales_rank": 22680, "product_subcategory": "Exercise & Fitness", "similar_product_ids": ["0060193395", "0812969472", "1579543081", "0972018417", "1579542921"], "review_helpful_votes": 2} +{"product_id": "0060193395", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 156, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} +{"product_id": "0694521485", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 72258, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} +{"product_id": "0694523194", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 89385, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} +{"product_id": "B00005B1ZW", "customer_id": "AA12M537YT203", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "Harold Robbins' Body Parts", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 35489, "product_subcategory": "Thrillers", "similar_product_ids": ["B00004YA1C", "B00009MEIH", "0780627792", "B00023P4I8", "B000059TP6"], "review_helpful_votes": 1} +{"product_id": "1573300780", "customer_id": "AA1G3JXDX6JQQ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "The Allman Brothers Band", "review_rating": 4, "product_category": "Music Video & Concerts", "product_sales_rank": 28164, "product_subcategory": "General", "similar_product_ids": ["B0000C7PWI", "B00008G83R", "6305130930", "B0002SPPSC", "6305019681"], "review_helpful_votes": 4} +{"product_id": "0965683621", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 61, "product_group": "Book", "product_title": "Race, Evolution, and Behavior ", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 401854, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 12} +{"product_id": "0965683605", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 62, "product_group": "Book", "product_title": "Race, Evolution, and Behavior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 146808, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 13} +{"product_id": "0965683613", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 62, "product_group": "Book", "product_title": "Race, Evolution, and Behavior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 121530, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 13} +{"product_id": "B00005RDSN", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Atlantis - The Lost Empire (Disney Collector's Edition)", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 12834, "product_subcategory": "Animation", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} +{"product_id": "B00005RDSQ", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 2377, "product_subcategory": "Animation", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} +{"product_id": "B00005RDVV", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 5875, "product_subcategory": "Adventure", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} +{"product_id": "B00005RDWG", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 19184, "product_subcategory": "Adventure", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} +{"product_id": "B00005N9CV", "customer_id": "AA7DSULMWBHOW", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Look of Love", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 603, "product_subcategory": "General", "similar_product_ids": ["B00000J7S8", "B000148KK2", "B00006J9OT", "B000003NA4", "B000003N89"], "review_helpful_votes": 3} +{"product_id": "B00006L6YH", "customer_id": "AA7DSULMWBHOW", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Look of Love (Hybr) (Ms)", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 102740, "product_subcategory": "General", "similar_product_ids": ["B00000J7S8", "B000148KK2", "B00006J9OT", "B000003NA4", "B000003N89"], "review_helpful_votes": 3} +{"product_id": "0240516648", "customer_id": "AAFRDBLLQ3TZJ", "review_date": {"$date": 1013644800000}, "review_votes": 24, "product_group": "Book", "product_title": "Real-time 3D Character Animation with Visual C++ (Book & CD-ROM)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 68934, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["1556229135", "1584502045", "0321228324", "1568811829", "1584502274"], "review_helpful_votes": 11} +{"product_id": "0316666009", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 7441, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} +{"product_id": "0446610038", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 3168, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} +{"product_id": "158621053X", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 395366, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446608815"], "review_helpful_votes": 7} +{"product_id": "1586210564", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Books on Tape", "product_sales_rank": 155998, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} +{"product_id": "1586210572", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die (Women's Murder Club (Audio))", "review_rating": 1, "product_category": "Books on CD", "product_sales_rank": 363732, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} +{"product_id": "1586210599", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die (Women's Murder Club (Audio))", "review_rating": 1, "product_category": "Books on CD", "product_sales_rank": 175694, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} +{"product_id": "B00004S2E9", "customer_id": "AAOTXJRW5HP94", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Essential Mix", "review_rating": 3, "product_category": "Dance & DJ", "product_sales_rank": 29813, "product_subcategory": "General", "similar_product_ids": ["B0001MLM1S", "B00005Q4PB", "B00000JG24", "B0006B2ACY", "B00009OKOQ"], "review_helpful_votes": 0} +{"product_id": "0130092290", "customer_id": "AAPBZ5T7COQBU", "review_date": {"$date": 1013644800000}, "review_votes": 68, "product_group": "Book", "product_title": "Core Servlets and JavaServer Pages, Vol. 1", "review_rating": 2, "product_category": "Computers & Internet", "product_sales_rank": 10577, "product_subcategory": "Web Development", "similar_product_ids": ["0130676144", "0131422464", "0131482025", "0596005725", "059600530X"], "review_helpful_votes": 63} +{"product_id": "0130893404", "customer_id": "AAPBZ5T7COQBU", "review_date": {"$date": 1013644800000}, "review_votes": 68, "product_group": "Book", "product_title": "Core Servlets and JavaServer Pages (JSP)", "review_rating": 2, "product_category": "Computers & Internet", "product_sales_rank": 63011, "product_subcategory": "Web Development", "similar_product_ids": ["0130676144", "0131422464", "0131482025", "0596005725", "059600530X"], "review_helpful_votes": 63} +{"product_id": "0968084206", "customer_id": "AAPYWOX2QGTYJ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Euchre", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 359946, "product_subcategory": "Games", "similar_product_ids": [], "review_helpful_votes": 4} +{"product_id": "0553528947", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away From Heaven", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 300617, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} +{"product_id": "0553582755", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away from Heaven", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18498, "product_subcategory": "Thrillers", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} +{"product_id": "0553801376", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away from Heaven", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 286350, "product_subcategory": "Thrillers", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} +{"product_id": "B000002V1I", "customer_id": "AAU5DBENOW7DM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Check Your Head", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 4183, "product_subcategory": "East Coast", "similar_product_ids": ["B000002TP7", "B000002UUN", "B0000024JN", "B000007TE8", "B00021LRWM"], "review_helpful_votes": 5} +{"product_id": "1930928513", "customer_id": "AAUT2ZCRMTT8H", "review_date": {"$date": 1013644800000}, "review_votes": 51, "product_group": "Book", "product_title": "Turning the Page", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 199670, "product_subcategory": "General", "similar_product_ids": ["1932300155", "1931513988", "193151397X", "1931513767", "1560234695"], "review_helpful_votes": 44} +{"product_id": "0792841638", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Hair", "review_rating": 5, "product_category": "Musicals & Performing Arts", "product_sales_rank": 1723, "product_subcategory": "General", "similar_product_ids": ["0783232071", "B00000K3TV", "0767827929", "B00000JYU8", "B000002W1S"], "review_helpful_votes": 0} +{"product_id": "B00004STCS", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Hair", "review_rating": 5, "product_category": "Musicals & Performing Arts", "product_sales_rank": 9708, "product_subcategory": "General", "similar_product_ids": ["0783232071", "B00000K3TV", "0767827929", "B00000JYU8", "B000002W1S"], "review_helpful_votes": 0} +{"product_id": "6302670306", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Video", "product_title": "Mindwalk", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1566, "product_subcategory": "General", "similar_product_ids": ["6305069743", "0553345729", "1570625190", "6302664845", "0385476760"], "review_helpful_votes": 6} +{"product_id": "0345361792", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 539, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} +{"product_id": "0345417976", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany (Ballantine Reader's Circle)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 26346, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} +{"product_id": "061303421X", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 494538, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} +{"product_id": "0679642595", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany (Modern Library)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 105174, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} +{"product_id": "B00005QXG9", "customer_id": "AB4QT2G99O7N0", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "C True Hollywood Stories", "review_rating": 1, "product_category": "Rap & Hip-Hop", "product_sales_rank": 110252, "product_subcategory": "East Coast", "similar_product_ids": ["B00009Y3PI", "B00000AFWY", "B00004UAOW", "B00007BH4Z", "B00027JYOE"], "review_helpful_votes": 0} +{"product_id": "1561709662", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Cards", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 803020, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "1576737330", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 4769, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "1576738108", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Gift Edition ", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 525856, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "1576738426", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Audio", "review_rating": 1, "product_category": "Books on Tape", "product_sales_rank": 205151, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "1576738574", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez (Leather Edition)", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 351854, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "1576739074", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez (Breakthrough Series)", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 110768, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} +{"product_id": "B00005NNOX", "customer_id": "AB8J6KKIATGL3", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Well", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 25222, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B000024QBF", "B00002487W", "B000024QBK", "B0001Z3TTI", "B000002VDZ"], "review_helpful_votes": 2} +{"product_id": "0449912639", "customer_id": "ABCNNP742AV30", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Girls ", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 35862, "product_subcategory": "General", "similar_product_ids": ["0449006158", "0449907503", "039305103X", "0345443934", "0767903986"], "review_helpful_votes": 0} +{"product_id": "0743442792", "customer_id": "ABCNNP742AV30", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Honored Society", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 542152, "product_subcategory": "Thrillers", "similar_product_ids": ["0671900153", "0762418397"], "review_helpful_votes": 2} +{"product_id": "0060184906", "customer_id": "ABF5FMMZPOLAF", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "The Golems of Gotham ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 641304, "product_subcategory": "General", "similar_product_ids": ["0312198655", "0312254180", "096795200X", "157322975X", "0618509283"], "review_helpful_votes": 4} +{"product_id": "B00008NRH0", "customer_id": "ABF5FMMZPOLAF", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "The Golems of Gotham", "review_rating": 5, "product_category": "", "product_sales_rank": 624527, "product_subcategory": "", "similar_product_ids": ["0312198655", "0312254180", "096795200X", "157322975X", "0618509283"], "review_helpful_votes": 4} +{"product_id": "630141277X", "customer_id": "ABFJYHVD8RHLE", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Working Girl", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 6883, "product_subcategory": "General", "similar_product_ids": ["B0000542C9", "B000059HAM", "B00000J123", "B00005S6K8", "6305696071"], "review_helpful_votes": 8} +{"product_id": "B000059HAK", "customer_id": "ABFJYHVD8RHLE", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "Working Girl", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 3752, "product_subcategory": "General", "similar_product_ids": ["B0000542C9", "B000059HAM", "B00000J123", "B00005S6K8", "6305696071"], "review_helpful_votes": 8} +{"product_id": "B00005BJXA", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Giant Gila Monster/The Wasp Woman", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23747, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} +{"product_id": "B00004W190", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Bad Girls Go To Hell/Another Day Another Man", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 40553, "product_subcategory": "General", "similar_product_ids": ["B000056NW6", "B0002IQB8U", "B00022PYRU", "B0002NRRQ0", "B0002W4TL2"], "review_helpful_votes": 2} +{"product_id": "B00005ALM0", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "The Violent Years/Girl Gang", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 15399, "product_subcategory": "General", "similar_product_ids": ["B00005ALLZ", "B0002235LM", "B00005LP6F", "B0002NRRT2", "B0000CG8H0"], "review_helpful_votes": 6} +{"product_id": "B00005B6KQ", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "The Notorious Daughter of Fanny Hill / The Head Mistress", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 20963, "product_subcategory": "General", "similar_product_ids": ["B0002W4TL2", "B00005MM5O", "B0002NRRQ0", "B0002EJ7JE", "B00005R1NR"], "review_helpful_votes": 7} +{"product_id": "B00005B6KQ", "customer_id": null, "review_date": {"$date": 1013644800000}, "review_votes": true, "product_group": false, "product_title": "The Notorious Daughter of Fanny Hill / The Head Mistress", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 20963, "product_subcategory": "General", "similar_product_ids": ["B0002W4TL2", "B00005MM5O", "B0002NRRQ0", "B0002EJ7JE", "B00005R1NR"], "review_helpful_votes": 7} +{"array": [1,2,3]} +{"array": [2,3,4]} +{"array": [3,4,5]} +{"array": [2,3]} +{"array": [2]} +{"array": [4,5]} +{"t": 1} +{"t": 99} +{"t": {}} +{"t": {"y": "z"}} +{"t": []} +{"t": [1]} +{"t": "x"} +{"t": "a"} +{"t": true} +{"t": false} +[1, 2, 3] +["a", "b", "c"] +1 +2 +3 +4 +5 +null +null +null +false +false +true +"aaa" +"bbb" +"ccc" +"ddd" \ No newline at end of file diff --git a/jsquery/expected/jsquery.out b/jsquery/expected/jsquery.out new file mode 100644 index 0000000000..e747d9a3f5 --- /dev/null +++ b/jsquery/expected/jsquery.out @@ -0,0 +1,2923 @@ +CREATE EXTENSION jsquery; +set escape_string_warning=off; +set standard_conforming_strings=on; +CREATE TABLE test_jsquery (v jsonb); +\copy test_jsquery from 'data/test_jsquery.data' +select 'asd.zzz = 13'::jsquery; + jsquery +------------------ + "asd"."zzz" = 13 +(1 row) + +select 'asd.zzz < 13'::jsquery; + jsquery +------------------ + "asd"."zzz" < 13 +(1 row) + +select 'asd(zzz < 13)'::jsquery; + jsquery +------------------ + "asd"."zzz" < 13 +(1 row) + +select 'asd(zzz < 13 AND x = true)'::jsquery; + jsquery +---------------------------------- + "asd"("zzz" < 13 AND "x" = true) +(1 row) + +select 'asd(zzz < 13 AND x = "true")'::jsquery; + jsquery +------------------------------------ + "asd"("zzz" < 13 AND "x" = "true") +(1 row) + +select 'asd(zzz < 13 AND x.zxc = "true")'::jsquery; + jsquery +------------------------------------------ + "asd"("zzz" < 13 AND "x"."zxc" = "true") +(1 row) + +select 'asd(zzz < 13 OR #.zxc = "true" /* test */)'::jsquery; + jsquery +--------------------------------------- + "asd"("zzz" < 13 OR #."zxc" = "true") +(1 row) + +select 'asd(* < 13 AND /* ttt */ #.zxc = "true")'::jsquery; + jsquery +------------------------------------ + "asd"(* < 13 AND #."zxc" = "true") +(1 row) + +select '(* < 13 AND #.zxc = "true")'::jsquery; + jsquery +------------------------------- + (* < 13 AND #."zxc" = "true") +(1 row) + +select '* < 13 AND #.zxc/* t2 */ = "true"'::jsquery; + jsquery +------------------------------- + (* < 13 AND #."zxc" = "true") +(1 row) + +select '* < 13 AND #.zxc"x" = "true"'::jsquery; +ERROR: bad jsquery representation +LINE 1: select '* < 13 AND #.zxc"x" = "true"'::jsquery; + ^ +DETAIL: syntax error, unexpected STRING_P at or near """ +select 'a < 1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < -1'::jsquery; + jsquery +---------- + "a" < -1 +(1 row) + +select 'a < +1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < .1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < -.1'::jsquery; + jsquery +------------ + "a" < -0.1 +(1 row) + +select 'a < +.1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < 0.1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < -0.1'::jsquery; + jsquery +------------ + "a" < -0.1 +(1 row) + +select 'a < +0.1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < 10.1'::jsquery; + jsquery +------------ + "a" < 10.1 +(1 row) + +select 'a < -10.1'::jsquery; + jsquery +------------- + "a" < -10.1 +(1 row) + +select 'a < +10.1'::jsquery; + jsquery +------------ + "a" < 10.1 +(1 row) + +select 'a < 1e1'::jsquery; + jsquery +---------- + "a" < 10 +(1 row) + +select 'a < -1e1'::jsquery; + jsquery +----------- + "a" < -10 +(1 row) + +select 'a < +1e1'::jsquery; + jsquery +---------- + "a" < 10 +(1 row) + +select 'a < .1e1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < -.1e1'::jsquery; + jsquery +---------- + "a" < -1 +(1 row) + +select 'a < +.1e1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < 0.1e1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < -0.1e1'::jsquery; + jsquery +---------- + "a" < -1 +(1 row) + +select 'a < +0.1e1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < 10.1e1'::jsquery; + jsquery +----------- + "a" < 101 +(1 row) + +select 'a < -10.1e1'::jsquery; + jsquery +------------ + "a" < -101 +(1 row) + +select 'a < +10.1e1'::jsquery; + jsquery +----------- + "a" < 101 +(1 row) + +select 'a < 1e-1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < -1e-1'::jsquery; + jsquery +------------ + "a" < -0.1 +(1 row) + +select 'a < +1e-1'::jsquery; + jsquery +----------- + "a" < 0.1 +(1 row) + +select 'a < .1e-1'::jsquery; + jsquery +------------ + "a" < 0.01 +(1 row) + +select 'a < -.1e-1'::jsquery; + jsquery +------------- + "a" < -0.01 +(1 row) + +select 'a < +.1e-1'::jsquery; + jsquery +------------ + "a" < 0.01 +(1 row) + +select 'a < 0.1e-1'::jsquery; + jsquery +------------ + "a" < 0.01 +(1 row) + +select 'a < -0.1e-1'::jsquery; + jsquery +------------- + "a" < -0.01 +(1 row) + +select 'a < +0.1e-1'::jsquery; + jsquery +------------ + "a" < 0.01 +(1 row) + +select 'a < 10.1e-1'::jsquery; + jsquery +------------ + "a" < 1.01 +(1 row) + +select 'a < -10.1e-1'::jsquery; + jsquery +------------- + "a" < -1.01 +(1 row) + +select 'a < +10.1e-1'::jsquery; + jsquery +------------ + "a" < 1.01 +(1 row) + +select 'a < 1e+1'::jsquery; + jsquery +---------- + "a" < 10 +(1 row) + +select 'a < -1e+1'::jsquery; + jsquery +----------- + "a" < -10 +(1 row) + +select 'a < +1e+1'::jsquery; + jsquery +---------- + "a" < 10 +(1 row) + +select 'a < .1e+1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < -.1e+1'::jsquery; + jsquery +---------- + "a" < -1 +(1 row) + +select 'a < +.1e+1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < 0.1e+1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < -0.1e+1'::jsquery; + jsquery +---------- + "a" < -1 +(1 row) + +select 'a < +0.1e+1'::jsquery; + jsquery +--------- + "a" < 1 +(1 row) + +select 'a < 10.1e+1'::jsquery; + jsquery +----------- + "a" < 101 +(1 row) + +select 'a < -10.1e+1'::jsquery; + jsquery +------------ + "a" < -101 +(1 row) + +select 'a < +10.1e+1'::jsquery; + jsquery +----------- + "a" < 101 +(1 row) + +select 'a in (0,1,2)'::jsquery; + jsquery +------------------ + "a" IN (0, 1, 2) +(1 row) + +select 'a IN (0,null, "null", xxx, "zzz", 2)'::jsquery; + jsquery +------------------------------------------- + "a" IN (0, null, "null", "xxx", "zzz", 2) +(1 row) + +select 'not < 1'::jsquery; + jsquery +----------- + "not" < 1 +(1 row) + +select 'not not < 1'::jsquery; + jsquery +----------------- + (NOT "not" < 1) +(1 row) + +select 'not( not < 1)'::jsquery; + jsquery +----------------- + (NOT "not" < 1) +(1 row) + +select 'not.x < 1'::jsquery; + jsquery +--------------- + "not"."x" < 1 +(1 row) + +select 'x.not < 1'::jsquery; + jsquery +--------------- + "x"."not" < 1 +(1 row) + +select 'a.%(not x > 0 and not (y < 0 or z = 0))'::jsquery; + jsquery +----------------------------------------------------- + "a".%((NOT "x" > 0) AND (NOT ("y" < 0 OR "z" = 0))) +(1 row) + +select 'is < 1'::jsquery; + jsquery +---------- + "is" < 1 +(1 row) + +select 'in < 1'::jsquery; + jsquery +---------- + "in" < 1 +(1 row) + +select 'not is < 1'::jsquery; + jsquery +---------------- + (NOT "is" < 1) +(1 row) + +select 'not in < 1'::jsquery; + jsquery +---------------- + (NOT "in" < 1) +(1 row) + +select 'in in (1,2)'::jsquery; + jsquery +---------------- + "in" IN (1, 2) +(1 row) + +select 'is in (1,2)'::jsquery; + jsquery +---------------- + "is" IN (1, 2) +(1 row) + +select 'not in (1,2)'::jsquery; + jsquery +----------------- + "not" IN (1, 2) +(1 row) + +select 'in is numeric'::jsquery; + jsquery +----------------- + "in" IS NUMERIC +(1 row) + +select 'is is numeric'::jsquery; + jsquery +----------------- + "is" IS NUMERIC +(1 row) + +select 'not is numeric'::jsquery; + jsquery +------------------ + "not" IS NUMERIC +(1 row) + +select 'not.in < 1'::jsquery; + jsquery +---------------- + "not"."in" < 1 +(1 row) + +select 'not.is < 1'::jsquery; + jsquery +---------------- + "not"."is" < 1 +(1 row) + +select 'not.not < 1'::jsquery; + jsquery +----------------- + "not"."not" < 1 +(1 row) + +select 'in.in < 1'::jsquery; + jsquery +--------------- + "in"."in" < 1 +(1 row) + +select 'in.is < 1'::jsquery; + jsquery +--------------- + "in"."is" < 1 +(1 row) + +select 'in.not < 1'::jsquery; + jsquery +---------------- + "in"."not" < 1 +(1 row) + +select 'is.in < 1'::jsquery; + jsquery +--------------- + "is"."in" < 1 +(1 row) + +select 'is.is < 1'::jsquery; + jsquery +--------------- + "is"."is" < 1 +(1 row) + +select 'is.not < 1'::jsquery; + jsquery +---------------- + "is"."not" < 1 +(1 row) + +select 'a.b.#4 > 4'::jsquery; + jsquery +---------------- + "a"."b".#4 > 4 +(1 row) + +select 'a.b.#10203.* > 4'::jsquery; + jsquery +---------------------- + "a"."b".#10203.* > 4 +(1 row) + +select '{"a": {"b": null}}'::jsonb @@ 'a.b = 1'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": null}}'::jsonb @@ 'a.b = null'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": null}}'::jsonb @@ 'a.b = false'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": false}}'::jsonb @@ 'a.b = false'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": false}}'::jsonb @@ 'a.b = true'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": true}}'::jsonb @@ 'a.b = true'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 1'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 1'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 1'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 1'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 1'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 2'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 2'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 0'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 0'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 0'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 1 ]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1 ]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1 ]'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1,2,3,4 ]'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1,2,3,4 ]'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 4'; + ?column? +---------- + f +(1 row) + +select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 3'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a = 4'; + ?column? +---------- + f +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a = 4'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 1 OR a=3)'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 OR a=1)'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=1)'; + ?column? +---------- + f +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=2)' as "false"; + false +------- + f +(1 row) + +select '[{"a": 2, "b":3}, {"a": 3, "b": 1}]'::jsonb @@ '#(b = 1 and a=3)'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a.a = 4'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a.a = 4'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.#.a.a = 4'; + ?column? +---------- + t +(1 row) + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.*.a.a = 4'; + ?column? +---------- + t +(1 row) + +select '{"a": 1}'::jsonb @@ 'a in (0,1,2)'; + ?column? +---------- + t +(1 row) + +select '{"a": 1}'::jsonb @@ 'a in (0,2)'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#=2'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 5 ]'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a=*'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b=*'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.c=*'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b = [1,2,3]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# = [1,2,3]'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b && [1,2,3]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# && [1,2,3]'; + ?column? +---------- + f +(1 row) + +select 'asd.# = 3'::jsquery & 'zzz = true' | 'xxx.# = zero'; + ?column? +------------------------------------------------------ + (("asd".# = 3 AND "zzz" = true) OR "xxx".# = "zero") +(1 row) + +select !'asd.# = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; + ?column? +------------------------------------------------------------------ + (((NOT "asd".# = 3) AND "zzz" = true) OR (NOT "xxx".# = "zero")) +(1 row) + +select !'asd.#3.f = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; + ?column? +----------------------------------------------------------------------- + (((NOT "asd".#3."f" = 3) AND "zzz" = true) OR (NOT "xxx".# = "zero")) +(1 row) + +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0]'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,1]'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,3]'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 2 ]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b($ && [ 2 ])'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b && [ 2 ]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b ($ && [ 2 ])'; + ?column? +---------- + t +(1 row) + +select '[1,2,3]'::jsonb @@ '# && [2]'; + ?column? +---------- + f +(1 row) + +select '[1,2,3]'::jsonb @@ '#($ && [2])'; + ?column? +---------- + f +(1 row) + +select '[1,2,3]'::jsonb @@ '$ && [2]'; + ?column? +---------- + t +(1 row) + +select '[1,2,3]'::jsonb @@ '$ ($ && [2])'; + ?column? +---------- + t +(1 row) + +select '[1,2,3]'::jsonb @@ '$ = 2'; + ?column? +---------- + f +(1 row) + +select '[1,2,3]'::jsonb @@ '# = 2'; + ?column? +---------- + t +(1 row) + +select '[1,2,3]'::jsonb @@ '#.$ = 2'; + ?column? +---------- + t +(1 row) + +select '[1,2,3]'::jsonb @@ '#($ = 2)'; + ?column? +---------- + t +(1 row) + +select '[3,4]'::jsonb @@ '#($ > 2 and $ < 5)'; + ?column? +---------- + t +(1 row) + +select '[3,4]'::jsonb @@ '# > 2 and # < 5'; + ?column? +---------- + t +(1 row) + +select '[1,6]'::jsonb @@ '#($ > 2 and $ < 5)'; + ?column? +---------- + f +(1 row) + +select '[1,6]'::jsonb @@ '# > 2 and # < 5'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.b=3'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ 'a.%=3'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.%="hey"'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%="hey"'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%=[5,6]'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#1 = 2'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#2 = 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#3 = 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#1.x = 2'; + ?column? +---------- + t +(1 row) + +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#2.x = 2'; + ?column? +---------- + f +(1 row) + +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#3.x = 2'; + ?column? +---------- + f +(1 row) + +select '"XXX"'::jsonb @@ '$="XXX"'; + ?column? +---------- + t +(1 row) + +select '"XXX"'::jsonb @@ '#.$="XXX"'; + ?column? +---------- + f +(1 row) + +--Unicode +select 'a\t = "dollar \u0024 character"'::jsquery; + jsquery +------------------------------ + "a\t" = "dollar $ character" +(1 row) + +select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar \u0024 character"'; + ?column? +---------- + t +(1 row) + +select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar $ character"'; + ?column? +---------- + t +(1 row) + +select '{ "a": "dollar $ character" }'::jsonb @@ '* = "dollar \u0024 character"'; + ?column? +---------- + t +(1 row) + +select 'a\r = "\n\""'::jsquery; + jsquery +---------------- + "a\r" = "\n\"" +(1 row) + +select 'a\r = "\u0000"'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = "\u0000"'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = \u0000'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = \u0000'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = "\abcd"'::jsquery AS err; +ERROR: bad jsquery representation +LINE 1: select 'a\r = "\abcd"'::jsquery AS err; + ^ +DETAIL: Escape sequence is invalid at or near "\a" +select 'a\r = "\\abcd"'::jsquery; + jsquery +------------------ + "a\r" = "\\abcd" +(1 row) + +select 'a\r = "x\u0000"'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = "x\u0000"'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = x\u0000'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = x\u0000'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = "x\abcd"'::jsquery AS err; +ERROR: bad jsquery representation +LINE 1: select 'a\r = "x\abcd"'::jsquery AS err; + ^ +DETAIL: Escape sequence is invalid at or near "\a" +select 'a\r = "x\\abcd"'::jsquery; + jsquery +------------------- + "a\r" = "x\\abcd" +(1 row) + +select 'a\r = "x\u0000x"'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = "x\u0000x"'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = x\u0000x'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = x\u0000x'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = "x\abcdx"'::jsquery AS err; +ERROR: bad jsquery representation +LINE 1: select 'a\r = "x\abcdx"'::jsquery AS err; + ^ +DETAIL: Escape sequence is invalid at or near "\a" +select 'a\r = "x\\abcdx"'::jsquery; + jsquery +-------------------- + "a\r" = "x\\abcdx" +(1 row) + +select 'a\r = "\u0000x"'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = "\u0000x"'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = \u0000x'::jsquery; +ERROR: unsupported Unicode escape sequence +LINE 1: select 'a\r = \u0000x'::jsquery; + ^ +DETAIL: \u0000 cannot be converted to text. +select 'a\r = "\abcdx"'::jsquery AS err; +ERROR: bad jsquery representation +LINE 1: select 'a\r = "\abcdx"'::jsquery AS err; + ^ +DETAIL: Escape sequence is invalid at or near "\a" +select 'a\r = "\\abcdx"'::jsquery; + jsquery +------------------- + "a\r" = "\\abcdx" +(1 row) + +select 'a\r = x"\\abcd"'::jsquery AS err; +ERROR: bad jsquery representation +LINE 1: select 'a\r = x"\\abcd"'::jsquery AS err; + ^ +DETAIL: syntax error, unexpected STRING_P, expecting $end at or near """ +--IS +select 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric OR as is string'::jsquery; + jsquery +------------------------------------------------------------------------------------------------- + (((("as" IS BOOLEAN OR "as" IS ARRAY) OR "as" IS OBJECT) OR "as" IS NUMERIC) OR "as" IS STRING) +(1 row) + +select '{"as": "xxx"}' @@ 'as IS string'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"as": "xxx"}' @@ 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"as": 5}' @@ 'as is Numeric'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"as": true}' @@ 'as is boolean'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"as": false}' @@ 'as is boolean'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"as": "false"}' @@ 'as is boolean'::jsquery; + ?column? +---------- + f +(1 row) + +select '["xxx"]' @@ '$ IS array'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"as": false}' @@ '$ IS object'::jsquery; + ?column? +---------- + t +(1 row) + +select '"xxx"' @@ '$ IS string'::jsquery; + ?column? +---------- + t +(1 row) + +select '"xxx"' @@ '$ IS numeric'::jsquery; + ?column? +---------- + f +(1 row) + +--hint +select 'a /*-- noindex */ = 5'::jsquery; + jsquery +-------------------------- + "a" /*-- noindex */ = 5 +(1 row) + +select 'a /*-- index */ = 5'::jsquery; + jsquery +------------------------ + "a" /*-- index */ = 5 +(1 row) + +select 'asd.# = 3'::jsquery & 'zzz /*-- noindex */ = true' | 'xxx.# /*-- index */ = zero'; + ?column? +-------------------------------------------------------------------------------------- + (("asd".# = 3 AND "zzz" /*-- noindex */ = true) OR "xxx".# /*-- index */ = "zero") +(1 row) + +select 'a /*-- xxx */ = 5'::jsquery; + jsquery +--------- + "a" = 5 +(1 row) + +select 'a /* index */ = 5'::jsquery; + jsquery +--------- + "a" = 5 +(1 row) + +select 'a /* noindex */ = 5'::jsquery; + jsquery +--------- + "a" = 5 +(1 row) + +select 'a = /*-- noindex */ 5'::jsquery; +ERROR: bad jsquery representation +LINE 1: select 'a = /*-- noindex */ 5'::jsquery; + ^ +DETAIL: syntax error, unexpected HINT_P at or near "*/" +select 'a = /* noindex */ 5'::jsquery; + jsquery +--------- + "a" = 5 +(1 row) + +--LENGTH +select 'a.@# = 4'::jsquery; + jsquery +------------ + "a".@# = 4 +(1 row) + +select 'a.@#.$ = 4'::jsquery as noerror; + noerror +-------------- + "a".@#.$ = 4 +(1 row) + +select 'a.@#.a = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.a = 4'::jsquery as error; + ^ +select 'a.@#.* = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.* = 4'::jsquery as error; + ^ +select 'a.@#.% = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.% = 4'::jsquery as error; + ^ +select 'a.@#.# = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.# = 4'::jsquery as error; + ^ +select 'a.@#.*: = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.*: = 4'::jsquery as error; + ^ +select 'a.@#.%: = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.%: = 4'::jsquery as error; + ^ +select 'a.@#.#: = 4'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@#.#: = 4'::jsquery as error; + ^ +select 'a.@# (a = 5 or b = 6)'::jsquery as error; +ERROR: Array length should be last in path +LINE 1: select 'a.@# (a = 5 or b = 6)'::jsquery as error; + ^ +select '[]' @@ '@# = 0'::jsquery; + ?column? +---------- + t +(1 row) + +select '[]' @@ '@# < 2'::jsquery; + ?column? +---------- + t +(1 row) + +select '[]' @@ '@# > 1'::jsquery; + ?column? +---------- + f +(1 row) + +select '[1]' @@ '@# = 0'::jsquery; + ?column? +---------- + f +(1 row) + +select '[1]' @@ '@# < 2'::jsquery; + ?column? +---------- + t +(1 row) + +select '[1]' @@ '@# > 1'::jsquery; + ?column? +---------- + f +(1 row) + +select '[1,2]' @@ '@# = 0'::jsquery; + ?column? +---------- + f +(1 row) + +select '[1,2]' @@ '@# < 2'::jsquery; + ?column? +---------- + f +(1 row) + +select '[1,2]' @@ '@# > 1'::jsquery; + ?column? +---------- + t +(1 row) + +select '[1,2]' @@ '@# in (1, 2)'::jsquery; + ?column? +---------- + t +(1 row) + +select '[1,2]' @@ '@# in (1, 3)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":[1,2]}' @@ '@# in (2, 4)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":[1,2]}' @@ 'a.@# in (2, 4)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":[1,2]}' @@ '@# = 1'::jsquery; + ?column? +---------- + t +(1 row) + +--ALL +select 'a.*: = 4'::jsquery; + jsquery +------------ + "a".*: = 4 +(1 row) + +select '%: = 4'::jsquery; + jsquery +--------- + %: = 4 +(1 row) + +select '#:.i = 4'::jsquery; + jsquery +------------ + #:."i" = 4 +(1 row) + +select '[]' @@ '#: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '[2,3,4]' @@ '#: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '[2,3,5]' @@ '#: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '[2,3,5]' @@ '# ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '[2,3,"x"]' @@ '#: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{}' @@ '%: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{}' @@ '*: ($ is object)'::jsquery; + ?column? +---------- + t +(1 row) + +select '"a"' @@ '*: is string'::jsquery; + ?column? +---------- + t +(1 row) + +select '1' @@ '*: is string'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":2,"b":3,"c":4}' @@ '%: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":2,"b":3,"c":5}' @@ '%: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":2,"b":3,"c":5}' @@ '% ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":2,"b":3,"c":"x"}' @@ '%: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":2,"b":3,"c":4}' @@ '*: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":2,"b":3,"c":5}' @@ '*: ($ > 1 and $ < 5)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":2,"b":3,"c":4}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":2,"b":3,"c":5}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 1 and $ < 5))'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 0 and $ < 5))'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 0 and $ < 5))'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '* ($ > 0 and $ < 5)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR $ is numeric)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is numeric)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":8}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":"x"}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":null}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '%:.aa is numeric'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1}, "b":{"aa":true, "bb":2}}' @@ '%:.aa is numeric'::jsquery; + ?column? +---------- + f +(1 row) + +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}, "aa":16}' @@ '*: (not $ is object or $.aa is numeric)'::jsquery; + ?column? +---------- + t +(1 row) + +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '*: (not $ is object or $.aa is numeric or % is object)'::jsquery; + ?column? +---------- + t +(1 row) + +SELECT 'test.# IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)'::jsquery; + jsquery +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + "test".# IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64) +(1 row) + +select '[]' @@ '(@# > 0 and #: = 16)'::jsquery; + ?column? +---------- + f +(1 row) + +select '[16]' @@ '(@# > 0 and #: = 16)'::jsquery; + ?column? +---------- + t +(1 row) + +--extract entries for index scan +SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); + gin_debug_query_path_value +---------------------------- + AND + + z = 5 , entry 0 + + OR + + x.y.a = 1 , entry 1 + + x.y.b = 2 , entry 2 + + +(1 row) + +SELECT gin_debug_query_path_value('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('#(x = "a" and y > 0 and y < 1 and z > 0)'); + gin_debug_query_path_value +---------------------------- + #.x = "a" , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); + gin_debug_query_path_value +----------------------------- + AND + + #.x = "a" , entry 0 + + #.y >= 0 , < 1 , entry 1 + + +(1 row) + +SELECT gin_debug_query_path_value('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); + gin_debug_query_path_value +----------------------------- + AND + + #.y > 0 , <= 1 , entry 0 + + #.z > 0 , entry 1 + + +(1 row) + +SELECT gin_debug_query_path_value('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); + gin_debug_query_path_value +---------------------------- + AND + + x = 1 , entry 0 + + OR + + y > 0 , < 1 , entry 1 + + z > 0 , entry 2 + + +(1 row) + +SELECT gin_debug_query_path_value('%.x = 1'); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('*.x = "b"'); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('x && [1,2,3]'); + gin_debug_query_path_value +---------------------------- + OR + + x.# = 1 , entry 0 + + x.# = 2 , entry 1 + + x.# = 3 , entry 2 + + +(1 row) + +SELECT gin_debug_query_path_value('x @> [1,2,3]'); + gin_debug_query_path_value +---------------------------- + AND + + x.# = 1 , entry 0 + + x.# = 2 , entry 1 + + x.# = 3 , entry 2 + + +(1 row) + +SELECT gin_debug_query_path_value('x <@ [1,2,3]'); + gin_debug_query_path_value +---------------------------- + OR + + x = [] , entry 0 + + x.# = 1 , entry 1 + + x.# = 2 , entry 2 + + x.# = 3 , entry 3 + + +(1 row) + +SELECT gin_debug_query_path_value('x = *'); + gin_debug_query_path_value +---------------------------- + x = * , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('x is boolean'); + gin_debug_query_path_value +---------------------------- + x IS boolean , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('x is string'); + gin_debug_query_path_value +---------------------------- + x IS string , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('x is numeric'); + gin_debug_query_path_value +---------------------------- + x IS numeric , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('x is array'); + gin_debug_query_path_value +---------------------------- + x IS array , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('x is object'); + gin_debug_query_path_value +---------------------------- + x IS object , entry 0 + + +(1 row) + +SELECT gin_debug_query_path_value('#:(x=1) AND %:(y=1) AND *:(z=1)'); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); + gin_debug_query_path_value +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_path_value('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); + gin_debug_query_path_value +---------------------------- + #.x = 1 , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); + gin_debug_query_value_path +---------------------------- + AND + + z = 5 , entry 0 + + OR + + x.y.a = 1 , entry 1 + + x.y.b = 2 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('#(x = "a" and y > 0 and y < 1 and z > 0)'); + gin_debug_query_value_path +---------------------------- + #.x = "a" , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); + gin_debug_query_value_path +----------------------------- + AND + + #.x = "a" , entry 0 + + #.y >= 0 , < 1 , entry 1 + + +(1 row) + +SELECT gin_debug_query_value_path('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); + gin_debug_query_value_path +----------------------------- + AND + + #.y > 0 , <= 1 , entry 0 + + #.z > 0 , entry 1 + + +(1 row) + +SELECT gin_debug_query_value_path('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); + gin_debug_query_value_path +---------------------------- + AND + + x = 1 , entry 0 + + OR + + y > 0 , < 1 , entry 1 + + z > 0 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('%.x = 1'); + gin_debug_query_value_path +---------------------------- + %.x = 1 , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('*.x = "b"'); + gin_debug_query_value_path +---------------------------- + *.x = "b" , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x && [1,2,3]'); + gin_debug_query_value_path +---------------------------- + OR + + x.# = 1 , entry 0 + + x.# = 2 , entry 1 + + x.# = 3 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('x @> [1,2,3]'); + gin_debug_query_value_path +---------------------------- + AND + + x.# = 1 , entry 0 + + x.# = 2 , entry 1 + + x.# = 3 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('x <@ [1,2,3]'); + gin_debug_query_value_path +---------------------------- + OR + + x = [] , entry 0 + + x.# = 1 , entry 1 + + x.# = 2 , entry 2 + + x.# = 3 , entry 3 + + +(1 row) + +SELECT gin_debug_query_value_path('x = [1,2,3]'); + gin_debug_query_value_path +---------------------------- + AND + + x.# = 1 , entry 0 + + x.# = 2 , entry 1 + + x.# = 3 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('x = *'); + gin_debug_query_value_path +---------------------------- + x = * , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x is boolean'); + gin_debug_query_value_path +---------------------------- + x IS boolean , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x is string'); + gin_debug_query_value_path +---------------------------- + x IS string , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x is numeric'); + gin_debug_query_value_path +---------------------------- + x IS numeric , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x is array'); + gin_debug_query_value_path +---------------------------- + x IS array , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('x is object'); + gin_debug_query_value_path +---------------------------- + x IS object , entry 0 + + +(1 row) + +SELECT gin_debug_query_value_path('#:(x=1) AND %:(y=1) AND *:(z=1)'); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); + gin_debug_query_value_path +---------------------------- + AND + + #.x = 1 , entry 0 + + %.y = 1 , entry 1 + + *.z = 1 , entry 2 + + +(1 row) + +SELECT gin_debug_query_value_path('(@# > 0 and #: = 16)'); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +SELECT gin_debug_query_value_path('*.@# ($ = 4 or $ = 2)'); + gin_debug_query_value_path +---------------------------- + NULL + + +(1 row) + +---table and index +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0; + count +------- + 654 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 19; + count +------- + 13 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 < 19; + count +------- + 985 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 >= 19; + count +------- + 16 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 <= 19; + count +------- + 988 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 = 19; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 16 AND + (v->>'review_helpful_votes')::int4 < 20; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + count +------- + 654 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; + count +------- + 13 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; + count +------- + 985 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; + count +------- + 16 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; + count +------- + 988 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; + count +------- + 54 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'customer_id = null'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_votes = true'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'product_group = false'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 't = *'; + count +------- + 10 +(1 row) + +select count(*) from test_jsquery where v @@ 't is boolean'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is string'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is numeric'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is object'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is boolean'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is string'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is numeric'; + count +------- + 5 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is object'; + count +------- + 1017 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; + count +------- + 51 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; + count +------- + 1001 +(1 row) + +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; + count +------- + 40 +(1 row) + +select count(*) from test_jsquery where v @@ '$ > 2'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ = false'; + count +------- + 2 +(1 row) + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; + v +------------------- + {"array": [2]} + {"array": [2, 3]} +(2 rows) + +select v from test_jsquery where v @@ 'array && [2,3]' order by v; + v +---------------------- + {"array": [2]} + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} + {"array": [3, 4, 5]} +(5 rows) + +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; + v +---------------------- + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} +(3 rows) + +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + v +------------------- + {"array": [2, 3]} +(1 row) + +create index t_idx on test_jsquery using gin (v jsonb_value_path_ops); +set enable_seqscan = off; +explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + QUERY PLAN +------------------------------------------------------------------------ + Aggregate + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) +(5 rows) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + count +------- + 654 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; + count +------- + 13 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; + count +------- + 985 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; + count +------- + 16 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; + count +------- + 988 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; + count +------- + 54 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'customer_id = null'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_votes = true'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'product_group = false'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 't = *'; + count +------- + 10 +(1 row) + +select count(*) from test_jsquery where v @@ 't is boolean'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is string'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is numeric'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is object'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is boolean'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is string'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is numeric'; + count +------- + 5 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is object'; + count +------- + 1017 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; + count +------- + 51 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; + count +------- + 1001 +(1 row) + +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ '$ > 2'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ = false'; + count +------- + 2 +(1 row) + +explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" <@ [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" <@ [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" && [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" && [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" @> [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" @> [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; + QUERY PLAN +-------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" = [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" = [2, 3]'::jsquery) +(6 rows) + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; + v +------------------- + {"array": [2]} + {"array": [2, 3]} +(2 rows) + +select v from test_jsquery where v @@ 'array && [2,3]' order by v; + v +---------------------- + {"array": [2]} + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} + {"array": [3, 4, 5]} +(5 rows) + +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; + v +---------------------- + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} +(3 rows) + +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + v +------------------- + {"array": [2, 3]} +(1 row) + +drop index t_idx; +create index t_idx on test_jsquery using gin (v jsonb_path_value_ops); +set enable_seqscan = off; +explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + QUERY PLAN +------------------------------------------------------------------------ + Aggregate + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) +(5 rows) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + count +------- + 654 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; + count +------- + 13 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; + count +------- + 985 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; + count +------- + 16 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; + count +------- + 988 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; + count +------- + 8 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; + count +------- + 54 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ 'customer_id = null'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'review_votes = true'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 'product_group = false'; + count +------- + 1 +(1 row) + +select count(*) from test_jsquery where v @@ 't = *'; + count +------- + 10 +(1 row) + +select count(*) from test_jsquery where v @@ 't is boolean'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is string'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is numeric'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ 't is object'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is boolean'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is string'; + count +------- + 4 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is numeric'; + count +------- + 5 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is array'; + count +------- + 2 +(1 row) + +select count(*) from test_jsquery where v @@ '$ is object'; + count +------- + 1017 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; + count +------- + 51 +(1 row) + +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; + count +------- + 1001 +(1 row) + +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; + count +------- + 7 +(1 row) + +select count(*) from test_jsquery where v @@ '$ > 2'; + count +------- + 3 +(1 row) + +select count(*) from test_jsquery where v @@ '$ = false'; + count +------- + 2 +(1 row) + +explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" <@ [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" <@ [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" && [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" && [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" @> [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" @> [2, 3]'::jsquery) +(6 rows) + +explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; + QUERY PLAN +-------------------------------------------------------------- + Sort + Sort Key: v + -> Bitmap Heap Scan on test_jsquery + Recheck Cond: (v @@ '"array" = [2, 3]'::jsquery) + -> Bitmap Index Scan on t_idx + Index Cond: (v @@ '"array" = [2, 3]'::jsquery) +(6 rows) + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; + v +------------------- + {"array": [2]} + {"array": [2, 3]} +(2 rows) + +select v from test_jsquery where v @@ 'array && [2,3]' order by v; + v +---------------------- + {"array": [2]} + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} + {"array": [3, 4, 5]} +(5 rows) + +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; + v +---------------------- + {"array": [2, 3]} + {"array": [1, 2, 3]} + {"array": [2, 3, 4]} +(3 rows) + +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + v +------------------- + {"array": [2, 3]} +(1 row) + +RESET enable_seqscan; diff --git a/jsquery/jsonb_gin_ops.c b/jsquery/jsonb_gin_ops.c new file mode 100644 index 0000000000..4c6491e63b --- /dev/null +++ b/jsquery/jsonb_gin_ops.c @@ -0,0 +1,1353 @@ +/*------------------------------------------------------------------------- + * + * jsonb_gin_ops.c + * Support GIN over jsonb with jsquery operation + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Alexander Korotkov + * + * IDENTIFICATION + * contrib/jsquery/jsonb_gin_ops.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/hash.h" +#include "access/skey.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_type.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/jsonb.h" + +#include "jsquery.h" + +typedef struct PathHashStack +{ + uint32 hash; + struct PathHashStack *parent; +} PathHashStack; + +typedef struct +{ + int32 vl_len_; + uint32 hash; + uint8 type; + char data[1]; +} GINKey; + +#define GINKEYLEN offsetof(GINKey, data) + +#define GINKeyTrue 0x80 +#define GINKeyMinusInf 0x80 +#define GINKeyEmptyArray 0x80 +#define GINKeyLenString (INTALIGN(offsetof(GINKey, data)) + sizeof(uint32)) +#define GINKeyLenNumeric(len) (INTALIGN(offsetof(GINKey, data)) + len) +#define GINKeyDataString(key) (*(uint32 *)((Pointer)key + INTALIGN(offsetof(GINKey, data)))) +#define GINKeyDataNumeric(key) ((Pointer)key + INTALIGN(offsetof(GINKey, data))) +#define GINKeyType(key) ((key)->type & 0x7F) +#define GINKeyIsTrue(key) ((key)->type & GINKeyTrue) +#define GINKeyIsMinusInf(key) ((key)->type & GINKeyMinusInf) +#define GINKeyIsEmptyArray(key) ((key)->type & GINKeyEmptyArray) + +#define BLOOM_BITS 2 +#define JsonbNestedContainsStrategyNumber 13 +#define JsQueryMatchStrategyNumber 14 + +typedef struct +{ + Datum *entries; + Pointer *extra_data; + bool *partial_match; + int *map; + int count, total; +} Entries; + +typedef struct +{ + ExtractedNode *root; + ExtractedNode *node; + uint32 hash; + bool lossyHash; + GINKey *rightBound; +} KeyExtra; + +static uint32 get_bloom_value(uint32 hash); +static uint32 get_path_bloom(PathHashStack *stack); +static GINKey *make_gin_key(JsonbValue *v, uint32 hash); +static GINKey *make_gin_key_string(uint32 hash); +static GINKey *make_gin_query_value_key(JsQueryItem *value, uint32 hash); +static GINKey *make_gin_query_key(ExtractedNode *node, bool *partialMatch, uint32 hash, KeyExtra *keyExtra); +static GINKey *make_gin_query_key_minus_inf(uint32 hash); +static int32 compare_gin_key_value(GINKey *arg1, GINKey *arg2); +static int add_entry(Entries *e, Datum key, Pointer extra, bool pmatch); + +PG_FUNCTION_INFO_V1(gin_compare_jsonb_value_path); +PG_FUNCTION_INFO_V1(gin_compare_partial_jsonb_value_path); +PG_FUNCTION_INFO_V1(gin_extract_jsonb_value_path); +PG_FUNCTION_INFO_V1(gin_extract_jsonb_query_value_path); +PG_FUNCTION_INFO_V1(gin_consistent_jsonb_value_path); +PG_FUNCTION_INFO_V1(gin_triconsistent_jsonb_value_path); +PG_FUNCTION_INFO_V1(gin_debug_query_value_path); + +Datum gin_compare_jsonb_value_path(PG_FUNCTION_ARGS); +Datum gin_compare_partial_jsonb_value_path(PG_FUNCTION_ARGS); +Datum gin_extract_jsonb_value_path(PG_FUNCTION_ARGS); +Datum gin_extract_jsonb_query_value_path(PG_FUNCTION_ARGS); +Datum gin_consistent_jsonb_value_path(PG_FUNCTION_ARGS); +Datum gin_triconsistent_jsonb_value_path(PG_FUNCTION_ARGS); +Datum gin_debug_query_value_path(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gin_compare_jsonb_path_value); +PG_FUNCTION_INFO_V1(gin_compare_partial_jsonb_path_value); +PG_FUNCTION_INFO_V1(gin_extract_jsonb_path_value); +PG_FUNCTION_INFO_V1(gin_extract_jsonb_query_path_value); +PG_FUNCTION_INFO_V1(gin_consistent_jsonb_path_value); +PG_FUNCTION_INFO_V1(gin_triconsistent_jsonb_path_value); +PG_FUNCTION_INFO_V1(gin_debug_query_path_value); + +Datum gin_compare_jsonb_path_value(PG_FUNCTION_ARGS); +Datum gin_compare_partial_jsonb_path_value(PG_FUNCTION_ARGS); +Datum gin_extract_jsonb_path_value(PG_FUNCTION_ARGS); +Datum gin_extract_jsonb_query_path_value(PG_FUNCTION_ARGS); +Datum gin_consistent_jsonb_path_value(PG_FUNCTION_ARGS); +Datum gin_triconsistent_jsonb_path_value(PG_FUNCTION_ARGS); +Datum gin_debug_query_path_value(PG_FUNCTION_ARGS); + +static int +add_entry(Entries *e, Datum key, Pointer extra, bool pmatch) +{ + int entryNum; + if (!e->entries) + { + e->total = 16; + e->entries = (Datum *)palloc(e->total * sizeof(Datum)); + e->extra_data = (Pointer *)palloc(e->total * sizeof(Pointer)); + e->partial_match = (bool *)palloc(e->total * sizeof(bool)); + } + if (e->count + 1 > e->total) + { + e->total *= 2; + e->entries = (Datum *)repalloc(e->entries, e->total * sizeof(Datum)); + e->extra_data = (Pointer *)repalloc(e->extra_data, e->total * sizeof(Pointer)); + e->partial_match = (bool *)repalloc(e->partial_match, e->total * sizeof(bool)); + } + entryNum = e->count; + e->count++; + e->entries[entryNum] = key; + e->extra_data[entryNum] = extra; + e->partial_match[entryNum] = pmatch; + return entryNum; +} + +static uint32 +get_bloom_value(uint32 hash) +{ + int i, j, vals[BLOOM_BITS], val, tmp; + uint32 res = 0; + for (i = 0; i < BLOOM_BITS; i++) + { + val = hash % (32 - i) + i; + hash /= (32 - i); + vals[i] = val; + + j = i; + while (j > 0 && vals[j] <= vals[j - 1]) + { + tmp = vals[j] - 1; + vals[j] = vals[j - 1]; + vals[j - 1] = tmp; + j--; + } + } + for (i = 0; i < BLOOM_BITS; i++) + { + res |= (1 << vals[i]); + } + return res; +} + +static uint32 +get_path_bloom(PathHashStack *stack) +{ + int i = 0; + uint32 res = 0, val; + + while (stack) + { + uint32 hash = stack->hash; + + val = get_bloom_value(hash); + + res |= val; + i++; + stack = stack->parent; + } + return res; +} + +static uint32 +get_query_path_bloom(PathItem *pathItem, bool *lossy) +{ + uint32 res = 0, val; + + *lossy = false; + while (pathItem) + { + uint32 hash; + + if (pathItem->type == iKey) + { + hash = hash_any((unsigned char *)pathItem->s, pathItem->len); + val = get_bloom_value(hash); + res |= val; + } + else if (pathItem->type == iAny || pathItem->type == iAnyKey) + { + *lossy = true; + } + + pathItem = pathItem->parent; + } + return res; +} + +#ifdef NOT_USED +static void +log_gin_key(GINKey *key) +{ + if (GINKeyType(key) == jbvNull) + { + elog(NOTICE, "hash = %X, NULL", key->hash); + } + else if (GINKeyType(key) == jbvBool) + { + if (GINKeyIsTrue(key)) + elog(NOTICE, "hash = %X, true", key->hash); + else + elog(NOTICE, "hash = %X, false", key->hash); + } + else if (GINKeyType(key) == jbvNumeric) + { + if (GINKeyIsMinusInf(key)) + { + elog(NOTICE, "hash = %X, -inf", key->hash); + } + else + { + char *s; + s = DatumGetCString(DirectFunctionCall1(numeric_out, PointerGetDatum(GINKeyDataNumeric(key)))); + elog(NOTICE, "hash = %X, \"%s\"", key->hash, s); + } + } + else if (GINKeyType(key) == jbvString) + { + elog(NOTICE, "hash = %X, %X", key->hash, GINKeyDataString(key)); + } + else + { + elog(ERROR, "GINKey must be scalar"); + } +} +#endif + +static GINKey * +make_gin_key(JsonbValue *v, uint32 hash) +{ + GINKey *key; + + if (v->type == jbvNull) + { + key = (GINKey *)palloc(GINKEYLEN); + key->type = v->type; + SET_VARSIZE(key, GINKEYLEN); + } + else if (v->type == jbvBool) + { + key = (GINKey *)palloc(GINKEYLEN); + key->type = v->type | (v->val.boolean ? GINKeyTrue : 0); + SET_VARSIZE(key, GINKEYLEN); + } + else if (v->type == jbvArray) + { + key = (GINKey *)palloc(GINKEYLEN); + key->type = v->type; + if (v->val.array.nElems == 0) + key->type |= GINKeyEmptyArray; + SET_VARSIZE(key, GINKEYLEN); + } + else if (v->type == jbvObject) + { + key = (GINKey *)palloc(GINKEYLEN); + key->type = v->type; + SET_VARSIZE(key, GINKEYLEN); + } + else if (v->type == jbvNumeric) + { + key = (GINKey *)palloc(GINKeyLenNumeric(VARSIZE_ANY(v->val.numeric))); + key->type = v->type; + memcpy(GINKeyDataNumeric(key), v->val.numeric, VARSIZE_ANY(v->val.numeric)); + SET_VARSIZE(key, GINKeyLenNumeric(VARSIZE_ANY(v->val.numeric))); + } + else if (v->type == jbvString) + { + key = (GINKey *)palloc(GINKeyLenString); + key->type = v->type; + GINKeyDataString(key) = hash_any((unsigned char *)v->val.string.val, + v->val.string.len); + SET_VARSIZE(key, GINKeyLenString); + } + else + { + elog(ERROR, "GINKey must be scalar"); + } + key->hash = hash; + return key; +} + +static GINKey * +make_gin_key_string(uint32 hash) +{ + GINKey *key; + + key = (GINKey *)palloc(GINKeyLenString); + key->type = jbvString; + GINKeyDataString(key) = 0; + SET_VARSIZE(key, GINKeyLenString); + key->hash = hash; + return key; +} + +static GINKey * +make_gin_query_value_key(JsQueryItem *value, uint32 hash) +{ + GINKey *key; + int32 len; + char *s; + Numeric numeric; + + switch(value->type) + { + case jqiNull: + key = (GINKey *)palloc(GINKEYLEN); + key->type = jbvNull; + SET_VARSIZE(key, GINKEYLEN); + break; + case jqiString: + key = (GINKey *)palloc(GINKeyLenString); + key->type = jbvString; + s = jsqGetString(value, &len); + GINKeyDataString(key) = hash_any((unsigned char *)s, len); + SET_VARSIZE(key, GINKeyLenString); + break; + case jqiBool: + key = (GINKey *)palloc(GINKEYLEN); + key->type = jbvBool | (jsqGetBool(value) ? GINKeyTrue : 0); + SET_VARSIZE(key, GINKEYLEN); + break; + case jqiNumeric: + numeric = jsqGetNumeric(value); + key = (GINKey *)palloc(GINKeyLenNumeric(VARSIZE_ANY(numeric))); + key->type = jbvNumeric; + memcpy(GINKeyDataNumeric(key), numeric, VARSIZE_ANY(numeric)); + SET_VARSIZE(key, GINKeyLenNumeric(VARSIZE_ANY(numeric))); + break; + default: + elog(ERROR,"Wrong state"); + } + + key->hash = hash; + return key; +} + +static GINKey * +make_gin_query_key(ExtractedNode *node, bool *partialMatch, uint32 hash, KeyExtra *keyExtra) +{ + JsonbValue v; + GINKey *key; + + switch (node->type) + { + case eExactValue: + key = make_gin_query_value_key(node->exactValue, hash); + break; + case eEmptyArray: + v.type = jbvArray; + v.val.array.nElems = 0; + key = make_gin_key(&v, hash); + break; + case eInequality: + *partialMatch = true; + if (node->bounds.leftBound) + key = make_gin_query_value_key(node->bounds.leftBound, hash); + else + key = make_gin_query_key_minus_inf(hash); + if (node->bounds.rightBound) + keyExtra->rightBound = make_gin_query_value_key(node->bounds.rightBound, hash); + else + keyExtra->rightBound = NULL; + break; + case eIs: + switch (node->isType) + { + case jbvArray: + *partialMatch = true; + v.type = jbvArray; + v.val.array.nElems = 1; + key = make_gin_key(&v, hash); + break; + case jbvObject: + *partialMatch = true; + v.type = jbvObject; + key = make_gin_key(&v, hash); + break; + case jbvString: + *partialMatch = true; + key = make_gin_key_string(hash); + break; + case jbvNumeric: + *partialMatch = true; + key = make_gin_query_key_minus_inf(hash); + break; + case jbvBool: + *partialMatch = true; + v.type = jbvBool; + v.val.boolean = false; + key = make_gin_key(&v, hash); + break; + case jbvNull: + v.type = jbvNull; + key = make_gin_key(&v, hash); + break; + default: + elog(ERROR,"Wrong type"); + return NULL; + } + break; + case eAny: + v.type = jbvNull; + key = make_gin_key(&v, hash); + *partialMatch = true; + break; + default: + elog(ERROR, "Wrong type"); + break; + } + return key; +} + + +static GINKey * +make_gin_query_key_minus_inf(uint32 hash) +{ + GINKey *key; + + key = (GINKey *)palloc(GINKEYLEN); + key->type = jbvNumeric | GINKeyMinusInf; + key->hash = hash; + SET_VARSIZE(key, GINKEYLEN); + return key; +} + +static bool +check_value_path_entry_handler(ExtractedNode *node, Pointer extra) +{ + return true; +} + +static int +make_value_path_entry_handler(ExtractedNode *node, Pointer extra) +{ + Entries *e = (Entries *)extra; + uint32 hash; + bool lossy, partialMatch = false; + GINKey *key; + KeyExtra *keyExtra; + int result; + + Assert(!isLogicalNodeType(node->type)); + + hash = get_query_path_bloom(node->path, &lossy); + keyExtra = (KeyExtra *)palloc(sizeof(KeyExtra)); + keyExtra->hash = hash; + keyExtra->node = node; + keyExtra->lossyHash = lossy; + + key = make_gin_query_key(node, &partialMatch, hash, keyExtra); + + result = add_entry(e, PointerGetDatum(key), (Pointer)keyExtra, + lossy | partialMatch); + return result; +} + +static int32 +compare_gin_key_value(GINKey *arg1, GINKey *arg2) +{ + if (GINKeyType(arg1) != GINKeyType(arg2)) + { + return (GINKeyType(arg1) > GINKeyType(arg2)) ? 1 : -1; + } + else + { + switch(GINKeyType(arg1)) + { + case jbvNull: + case jbvArray: + if (GINKeyIsEmptyArray(arg1) == GINKeyIsEmptyArray(arg2)) + return 0; + else if (GINKeyIsEmptyArray(arg1) > GINKeyIsEmptyArray(arg2)) + return 1; + else + return -1; + case jbvObject: + return 0; + case jbvBool: + if (GINKeyIsTrue(arg1) == GINKeyIsTrue(arg2)) + return 0; + else if (GINKeyIsTrue(arg1) > GINKeyIsTrue(arg2)) + return 1; + else + return -1; + case jbvNumeric: + if (GINKeyIsMinusInf(arg1)) + { + if (GINKeyIsMinusInf(arg2)) + return 0; + else + return -1; + } + else + { + if (GINKeyIsMinusInf(arg2)) + return 1; + } + return DatumGetInt32(DirectFunctionCall2(numeric_cmp, + PointerGetDatum(GINKeyDataNumeric(arg1)), + PointerGetDatum(GINKeyDataNumeric(arg2)))); + case jbvString: + if (GINKeyDataString(arg1) < GINKeyDataString(arg2)) + return -1; + else if (GINKeyDataString(arg1) == GINKeyDataString(arg2)) + return 0; + else + return 1; + default: + elog(ERROR, "GINKey must be scalar"); + return 0; + } + } +} + +Datum +gin_compare_jsonb_value_path(PG_FUNCTION_ARGS) +{ + GINKey *arg1 = (GINKey *)PG_GETARG_VARLENA_P(0); + GINKey *arg2 = (GINKey *)PG_GETARG_VARLENA_P(1); + int32 result = 0; + + result = compare_gin_key_value(arg1, arg2); + if (result == 0 && arg1->hash != arg2->hash) + { + result = (arg1->hash > arg2->hash) ? 1 : -1; + } + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + PG_RETURN_INT32(result); +} + +Datum +gin_compare_partial_jsonb_value_path(PG_FUNCTION_ARGS) +{ + GINKey *partial_key = (GINKey *)PG_GETARG_VARLENA_P(0); + GINKey *key = (GINKey *)PG_GETARG_VARLENA_P(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + int32 result; + + if (strategy == JsQueryMatchStrategyNumber) + { + KeyExtra *extra = (KeyExtra *)PG_GETARG_POINTER(3); + ExtractedNode *node = extra->node; + + switch (node->type) + { + case eExactValue: + case eEmptyArray: + result = compare_gin_key_value(key, partial_key); + break; + case eInequality: + result = 0; + if (!node->bounds.leftInclusive && + compare_gin_key_value(key, partial_key) <= 0) + { + result = -1; + } + if (result == 0 && extra->rightBound) + { + result = compare_gin_key_value(key, extra->rightBound); + if ((node->bounds.rightInclusive && result <= 0) + || result < 0) + result = 0; + else + result = 1; + } + break; + case eIs: + if (node->isType == GINKeyType(key)) + result = 0; + else + result = (GINKeyType(key) > node->isType) ? 1 : -1; + break; + case eAny: + result = 0; + break; + default: + elog(ERROR, "Wrong type"); + break; + } + + if (result == 0) + { + if (extra->lossyHash) + { + if ((key->hash & extra->hash) != extra->hash) + result = -1; + } + else + { + if (key->hash != extra->hash) + result = -1; + } + } + } + else + { + uint32 *extra_data = (uint32 *)PG_GETARG_POINTER(3); + uint32 bloom = *extra_data; + + result = compare_gin_key_value(key, partial_key); + + if (result == 0) + { + if ((key->hash & bloom) != bloom) + result = -1; + } + } + + PG_FREE_IF_COPY(partial_key, 0); + PG_FREE_IF_COPY(key, 1); + PG_RETURN_INT32(result); +} + +static Datum * +gin_extract_jsonb_value_path_internal(Jsonb *jb, int32 *nentries, uint32 **bloom) +{ + int total = 2 * JB_ROOT_COUNT(jb); + JsonbIterator *it; + JsonbValue v; + PathHashStack *stack; + int i = 0, + r; + Datum *entries = NULL; + uint32 hash; + + if (total == 0) + { + *nentries = 0; + return NULL; + } + + entries = (Datum *) palloc(sizeof(Datum) * total); + if (bloom) + (*bloom) = (uint32 *) palloc(sizeof(uint32) * total); + + it = JsonbIteratorInit(&jb->root); + + stack = NULL; + + while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) + { + PathHashStack *tmp; + + if (i >= total) + { + total *= 2; + entries = (Datum *) repalloc(entries, sizeof(Datum) * total); + if (bloom) + (*bloom) = (uint32 *) repalloc(*bloom, sizeof(uint32) * total); + } + + switch (r) + { + case WJB_BEGIN_ARRAY: + if (!v.val.array.rawScalar) + entries[i++] = PointerGetDatum(make_gin_key(&v, get_path_bloom(stack))); + break; + case WJB_BEGIN_OBJECT: + entries[i++] = PointerGetDatum(make_gin_key(&v, get_path_bloom(stack))); + tmp = stack; + stack = (PathHashStack *) palloc(sizeof(PathHashStack)); + stack->parent = tmp; + break; + case WJB_KEY: + if (!stack) /* should never happen */ + elog(ERROR, "error jsonb iteration"); + stack->hash = 0; + JsonbHashScalarValue(&v, &stack->hash); + break; + case WJB_ELEM: + case WJB_VALUE: + if (bloom) + { + (*bloom)[i] = get_path_bloom(stack); + hash = 0; + } + else + { + hash = get_path_bloom(stack); + } + entries[i++] = PointerGetDatum(make_gin_key(&v, hash)); + break; + case WJB_END_OBJECT: + /* Pop the stack */ + if (!stack) /* should never happen */ + elog(ERROR, "error jsonb iteration"); + tmp = stack->parent; + pfree(stack); + stack = tmp; + break; + case WJB_END_ARRAY: + break; + default: + elog(ERROR, "invalid JsonbIteratorNext rc: %d", r); + } + } + + *nentries = i; + + return entries; +} + +Datum +gin_extract_jsonb_value_path(PG_FUNCTION_ARGS) +{ + Jsonb *jb = PG_GETARG_JSONB_P(0); + int32 *nentries = (int32 *) PG_GETARG_POINTER(1); + + PG_RETURN_POINTER(gin_extract_jsonb_value_path_internal(jb, nentries, NULL)); +} + +Datum +gin_debug_query_value_path(PG_FUNCTION_ARGS) +{ + JsQuery *jq; + Entries e = {0}; + char *s; + + jq = PG_GETARG_JSQUERY(0); + s = debugJsQuery(jq, make_value_path_entry_handler, + check_value_path_entry_handler, (Pointer)&e); + PG_RETURN_TEXT_P(cstring_to_text(s)); +} + +Datum +gin_extract_jsonb_query_value_path(PG_FUNCTION_ARGS) +{ + Jsonb *jb; + int32 *nentries = (int32 *) PG_GETARG_POINTER(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + bool **pmatch = (bool **) PG_GETARG_POINTER(3); + Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); + int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); + Datum *entries = NULL; + int i, n; + uint32 *bloom; + Entries e = {0}; + JsQuery *jq; + ExtractedNode *root; + + switch(strategy) + { + case JsonbContainsStrategyNumber: + jb = PG_GETARG_JSONB_P(0); + entries = gin_extract_jsonb_value_path_internal(jb, nentries, NULL); + break; + + case JsonbNestedContainsStrategyNumber: + jb = PG_GETARG_JSONB_P(0); + entries = gin_extract_jsonb_value_path_internal(jb, nentries, &bloom); + + n = *nentries; + *pmatch = (bool *) palloc(sizeof(bool) * n); + for (i = 0; i < n; i++) + (*pmatch)[i] = true; + + *extra_data = (Pointer *) palloc(sizeof(Pointer) * n); + for (i = 0; i < n; i++) + (*extra_data)[i] = (Pointer)&bloom[i]; + break; + + case JsQueryMatchStrategyNumber: + jq = PG_GETARG_JSQUERY(0); + root = extractJsQuery(jq, make_value_path_entry_handler, + check_value_path_entry_handler, (Pointer)&e); + if (root) + { + *nentries = e.count; + entries = e.entries; + *pmatch = e.partial_match; + *extra_data = e.extra_data; + for (i = 0; i < e.count; i++) + ((KeyExtra *)e.extra_data[i])->root = root; + } + else + { + entries = NULL; + *nentries = 0; + } + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + /* ...although "contains {}" requires a full index scan */ + if (entries == NULL) + *searchMode = GIN_SEARCH_MODE_ALL; + + PG_RETURN_POINTER(entries); +} + +Datum +gin_consistent_jsonb_value_path(PG_FUNCTION_ARGS) +{ + bool *check = (bool *) PG_GETARG_POINTER(0); + StrategyNumber strategy = PG_GETARG_UINT16(1); + /* Jsonb *query = PG_GETARG_JSONB_P(2); */ + int32 nkeys = PG_GETARG_INT32(3); + Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); + bool *recheck = (bool *) PG_GETARG_POINTER(5); + bool res = true; + int32 i; + + *recheck = true; + switch (strategy) + { + case JsonbContainsStrategyNumber: + case JsonbNestedContainsStrategyNumber: + for (i = 0; i < nkeys; i++) + { + if (!check[i]) + { + res = false; + break; + } + } + break; + + case JsQueryMatchStrategyNumber: + if (nkeys == 0) + res = true; + else + res = execRecursive(((KeyExtra *)extra_data[0])->root, check); + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + PG_RETURN_BOOL(res); +} + +Datum +gin_triconsistent_jsonb_value_path(PG_FUNCTION_ARGS) +{ + GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0); + StrategyNumber strategy = PG_GETARG_UINT16(1); + /* Jsonb *query = PG_GETARG_JSONB_P(2); */ + int32 nkeys = PG_GETARG_INT32(3); + Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); + GinTernaryValue res = GIN_TRUE; + int32 i; + bool has_maybe = false; + + switch (strategy) + { + case JsonbContainsStrategyNumber: + case JsonbNestedContainsStrategyNumber: + /* + * All extracted keys must be present. A combination of GIN_MAYBE and + * GIN_TRUE induces a GIN_MAYBE result, because then all keys may be + * present. + */ + for (i = 0; i < nkeys; i++) + { + if (check[i] == GIN_FALSE) + { + res = GIN_FALSE; + break; + } + if (check[i] == GIN_MAYBE) + { + res = GIN_MAYBE; + has_maybe = true; + } + } + + /* + * jsonb_hash_ops index doesn't have information about correspondence of + * Jsonb keys and values (as distinct from GIN keys, which for this opclass + * are a hash of a pair, or a hash of just an element), so invariably we + * recheck. This is also reflected in how GIN_MAYBE is given in response + * to there being no GIN_MAYBE input. + */ + if (!has_maybe && res == GIN_TRUE) + res = GIN_MAYBE; + break; + + case JsQueryMatchStrategyNumber: + if (nkeys == 0) + res = GIN_MAYBE; + else + res = execRecursiveTristate(((KeyExtra *)extra_data[0])->root, check); + + if (res == GIN_TRUE) + res = GIN_MAYBE; + + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + PG_RETURN_GIN_TERNARY_VALUE(res); +} + +static bool +get_query_path_hash(PathItem *pathItem, uint32 *hash) +{ + check_stack_depth(); + + if (!pathItem) + return true; + + if (!get_query_path_hash(pathItem->parent, hash)) + { + return false; + } + else + { + if (pathItem->type == iAny || pathItem->type == iAnyKey) + { + return false; + } + else + { + if (pathItem->type == iKey) + { + *hash = (*hash << 1) | (*hash >> 31); + *hash ^= hash_any((unsigned char *)pathItem->s, pathItem->len); + } + else if (pathItem->type == iAnyArray || pathItem->type == iIndexArray) + { + *hash = (*hash << 1) | (*hash >> 31); + *hash ^= JB_FARRAY; + } + return true; + } + } +} + +static bool +check_path_value_entry_handler(ExtractedNode *node, Pointer extra) +{ + uint32 hash; + hash = 0; + if (!get_query_path_hash(node->path, &hash)) + return false; + return true; +} + +static int +make_path_value_entry_handler(ExtractedNode *node, Pointer extra) +{ + Entries *e = (Entries *)extra; + uint32 hash; + GINKey *key; + KeyExtra *keyExtra; + int result; + bool partialMatch = false; + + Assert(!isLogicalNodeType(node->type)); + + hash = 0; + if (!get_query_path_hash(node->path, &hash)) + return -1; + + keyExtra = (KeyExtra *)palloc(sizeof(KeyExtra)); + keyExtra->hash = hash; + keyExtra->node = node; + key = make_gin_query_key(node, &partialMatch, hash, keyExtra); + + result = add_entry(e, PointerGetDatum(key), (Pointer)keyExtra, partialMatch); + return result; +} + +Datum +gin_compare_jsonb_path_value(PG_FUNCTION_ARGS) +{ + GINKey *arg1 = (GINKey *)PG_GETARG_VARLENA_P(0); + GINKey *arg2 = (GINKey *)PG_GETARG_VARLENA_P(1); + int32 result = 0; + + if (arg1->hash != arg2->hash) + { + result = (arg1->hash > arg2->hash) ? 1 : -1; + } + else + { + result = compare_gin_key_value(arg1, arg2); + } + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + PG_RETURN_INT32(result); +} + +Datum +gin_compare_partial_jsonb_path_value(PG_FUNCTION_ARGS) +{ + GINKey *partial_key = (GINKey *)PG_GETARG_VARLENA_P(0); + GINKey *key = (GINKey *)PG_GETARG_VARLENA_P(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + int32 result; + + if (key->hash != partial_key->hash) + { + result = (key->hash > partial_key->hash) ? 1 : -1; + } + else if (strategy == JsQueryMatchStrategyNumber) + { + KeyExtra *extra = (KeyExtra *)PG_GETARG_POINTER(3); + ExtractedNode *node = extra->node; + + switch (node->type) + { + case eInequality: + result = 0; + if (!node->bounds.leftInclusive && + compare_gin_key_value(key, partial_key) <= 0) + { + result = -1; + } + if (result == 0 && extra->rightBound) + { + result = compare_gin_key_value(key, extra->rightBound); + if ((node->bounds.rightInclusive && result <= 0) + || result < 0) + result = 0; + else + result = 1; + } + break; + case eIs: + if (node->isType == GINKeyType(key)) + result = 0; + else + result = (GINKeyType(key) > node->isType) ? 1 : -1; + break; + case eAny: + result = 0; + break; + default: + elog(ERROR, "Wrong type"); + break; + } + } + else + { + result = compare_gin_key_value(key, partial_key); + } + + PG_FREE_IF_COPY(partial_key, 0); + PG_FREE_IF_COPY(key, 1); + PG_RETURN_INT32(result); +} + +static Datum * +gin_extract_jsonb_path_value_internal(Jsonb *jb, int32 *nentries) +{ + int total = 2 * JB_ROOT_COUNT(jb); + JsonbIterator *it; + JsonbValue v; + PathHashStack tail; + PathHashStack *stack; + int i = 0, + r; + Datum *entries = NULL; + + if (total == 0) + { + *nentries = 0; + return NULL; + } + + entries = (Datum *) palloc(sizeof(Datum) * total); + + it = JsonbIteratorInit(&jb->root); + + tail.parent = NULL; + tail.hash = 0; + stack = &tail; + + while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) + { + PathHashStack *tmp; + + if (i >= total) + { + total *= 2; + entries = (Datum *) repalloc(entries, sizeof(Datum) * total); + } + + if (!stack) /* should never happen */ + elog(ERROR, "error jsonb iteration"); + + switch (r) + { + case WJB_BEGIN_ARRAY: + if (v.val.array.rawScalar) + break; + entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); + tmp = stack; + stack = (PathHashStack *) palloc(sizeof(PathHashStack)); + stack->parent = tmp; + stack->hash = stack->parent->hash; + stack->hash = (stack->hash << 1) | (stack->hash >> 31); + stack->hash ^= JB_FARRAY; + break; + case WJB_BEGIN_OBJECT: + entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); + tmp = stack; + stack = (PathHashStack *) palloc(sizeof(PathHashStack)); + stack->parent = tmp; + stack->hash = stack->parent->hash; + break; + case WJB_KEY: + /* Initialize hash from parent */ + if (!stack->parent) /* should never happen */ + elog(ERROR, "error jsonb iteration"); + stack->hash = stack->parent->hash; + JsonbHashScalarValue(&v, &stack->hash); + break; + case WJB_ELEM: + case WJB_VALUE: + /* Element/value case */ + entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); + break; + case WJB_END_ARRAY: + if (!stack->parent) + break; /* raw scalar array */ + /* fall through */ + case WJB_END_OBJECT: + /* Pop the stack */ + tmp = stack->parent; + pfree(stack); + stack = tmp; + break; + default: + elog(ERROR, "invalid JsonbIteratorNext rc: %d", r); + } + } + + *nentries = i; + + return entries; +} + +Datum +gin_extract_jsonb_path_value(PG_FUNCTION_ARGS) +{ + Jsonb *jb = PG_GETARG_JSONB_P(0); + int32 *nentries = (int32 *) PG_GETARG_POINTER(1); + + PG_RETURN_POINTER(gin_extract_jsonb_path_value_internal(jb, nentries)); +} + +Datum +gin_debug_query_path_value(PG_FUNCTION_ARGS) +{ + JsQuery *jq; + Entries e = {0}; + char *s; + + + jq = PG_GETARG_JSQUERY(0); + s = debugJsQuery(jq, make_path_value_entry_handler, + check_path_value_entry_handler, (Pointer)&e); + PG_RETURN_TEXT_P(cstring_to_text(s)); +} + +Datum +gin_extract_jsonb_query_path_value(PG_FUNCTION_ARGS) +{ + Jsonb *jb; + int32 *nentries = (int32 *) PG_GETARG_POINTER(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + bool **pmatch = (bool **) PG_GETARG_POINTER(3); + Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); + int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); + Datum *entries = NULL; + int i; + Entries e = {0}; + JsQuery *jq; + ExtractedNode *root; + + switch(strategy) + { + case JsonbContainsStrategyNumber: + jb = PG_GETARG_JSONB_P(0); + entries = gin_extract_jsonb_path_value_internal(jb, nentries); + break; + + case JsQueryMatchStrategyNumber: + jq = PG_GETARG_JSQUERY(0); + root = extractJsQuery(jq, make_path_value_entry_handler, + check_path_value_entry_handler, (Pointer)&e); + if (root) + { + *nentries = e.count; + entries = e.entries; + *pmatch = e.partial_match; + *extra_data = e.extra_data; + for (i = 0; i < e.count; i++) + ((KeyExtra *)e.extra_data[i])->root = root; + } + else + { + entries = NULL; + *nentries = 0; + } + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + /* ...although "contains {}" requires a full index scan */ + if (entries == NULL) + *searchMode = GIN_SEARCH_MODE_ALL; + + PG_RETURN_POINTER(entries); +} + +Datum +gin_consistent_jsonb_path_value(PG_FUNCTION_ARGS) +{ + bool *check = (bool *) PG_GETARG_POINTER(0); + StrategyNumber strategy = PG_GETARG_UINT16(1); + /* Jsonb *query = PG_GETARG_JSONB_P(2); */ + int32 nkeys = PG_GETARG_INT32(3); + Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); + bool *recheck = (bool *) PG_GETARG_POINTER(5); + bool res = true; + int32 i; + + *recheck = true; + switch (strategy) + { + case JsonbContainsStrategyNumber: + for (i = 0; i < nkeys; i++) + { + if (!check[i]) + { + res = false; + break; + } + } + break; + + case JsQueryMatchStrategyNumber: + if (nkeys == 0) + res = true; + else + res = execRecursive(((KeyExtra *)extra_data[0])->root, check); + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + PG_RETURN_BOOL(res); +} + +Datum +gin_triconsistent_jsonb_path_value(PG_FUNCTION_ARGS) +{ + GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0); + StrategyNumber strategy = PG_GETARG_UINT16(1); + /* Jsonb *query = PG_GETARG_JSONB_P(2); */ + int32 nkeys = PG_GETARG_INT32(3); + Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); + GinTernaryValue res = GIN_TRUE; + int32 i; + bool has_maybe = false; + + + switch (strategy) + { + case JsonbContainsStrategyNumber: + /* + * All extracted keys must be present. A combination of GIN_MAYBE and + * GIN_TRUE induces a GIN_MAYBE result, because then all keys may be + * present. + */ + for (i = 0; i < nkeys; i++) + { + if (check[i] == GIN_FALSE) + { + res = GIN_FALSE; + break; + } + if (check[i] == GIN_MAYBE) + { + res = GIN_MAYBE; + has_maybe = true; + } + } + + /* + * jsonb_hash_ops index doesn't have information about correspondence of + * Jsonb keys and values (as distinct from GIN keys, which for this opclass + * are a hash of a pair, or a hash of just an element), so invariably we + * recheck. This is also reflected in how GIN_MAYBE is given in response + * to there being no GIN_MAYBE input. + */ + if (!has_maybe && res == GIN_TRUE) + res = GIN_MAYBE; + break; + + case JsQueryMatchStrategyNumber: + if (nkeys == 0) + res = GIN_MAYBE; + else + res = execRecursiveTristate(((KeyExtra *)extra_data[0])->root, check); + + if (res == GIN_TRUE) + res = GIN_MAYBE; + + break; + + default: + elog(ERROR, "unrecognized strategy number: %d", strategy); + break; + } + + PG_RETURN_GIN_TERNARY_VALUE(res); +} + diff --git a/jsquery/jsquery--1.0.sql b/jsquery/jsquery--1.0.sql new file mode 100644 index 0000000000..3bf1d9bc17 --- /dev/null +++ b/jsquery/jsquery--1.0.sql @@ -0,0 +1,293 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION jsquery" to load this file. \quit + +CREATE TYPE jsquery; + +CREATE FUNCTION jsquery_in(cstring) + RETURNS jsquery + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_out(jsquery) + RETURNS cstring + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE TYPE jsquery ( + INTERNALLENGTH = -1, + INPUT = jsquery_in, + OUTPUT = jsquery_out, + STORAGE = extended +); + +CREATE FUNCTION jsquery_json_exec(jsquery, jsonb) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION json_jsquery_exec(jsonb, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR @@ ( + LEFTARG = jsquery, + RIGHTARG = jsonb, + PROCEDURE = jsquery_json_exec, + COMMUTATOR = '@@', + RESTRICT = contsel, + JOIN = contjoinsel +); + +CREATE OPERATOR @@ ( + LEFTARG = jsonb, + RIGHTARG = jsquery, + PROCEDURE = json_jsquery_exec, + COMMUTATOR = '@@', + RESTRICT = contsel, + JOIN = contjoinsel +); + +CREATE FUNCTION jsquery_join_and(jsquery, jsquery) + RETURNS jsquery + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR & ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_join_and, + COMMUTATOR = '&' +); + +CREATE FUNCTION jsquery_join_or(jsquery, jsquery) + RETURNS jsquery + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR | ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_join_or, + COMMUTATOR = '|' +); + +CREATE FUNCTION jsquery_not(jsquery) + RETURNS jsquery + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR ! ( + RIGHTARG = jsquery, + PROCEDURE = jsquery_not +); + +CREATE FUNCTION jsquery_lt(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_le(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_eq(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_ne(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_ge(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE FUNCTION jsquery_gt(jsquery, jsquery) + RETURNS bool + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR < ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_lt, + COMMUTATOR = '>', + NEGATOR = '>=', + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_le, + COMMUTATOR = '>=', + NEGATOR = '>', + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR = ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_eq, + COMMUTATOR = '=', + NEGATOR = '<>', + RESTRICT = eqsel, + JOIN = eqjoinsel, + HASHES, + MERGES +); + +CREATE OPERATOR <> ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_eq, + COMMUTATOR = '<>', + NEGATOR = '=', + RESTRICT = neqsel, + JOIN = neqjoinsel +); + +CREATE OPERATOR >= ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_ge, + COMMUTATOR = '<=', + NEGATOR = '<', + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR > ( + LEFTARG = jsquery, + RIGHTARG = jsquery, + PROCEDURE = jsquery_ge, + COMMUTATOR = '<', + NEGATOR = '<=', + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE FUNCTION jsquery_cmp(jsquery, jsquery) + RETURNS int4 + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR CLASS jsquery_ops + DEFAULT FOR TYPE jsquery USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 >, + FUNCTION 1 jsquery_cmp(jsquery, jsquery); + +CREATE FUNCTION jsquery_hash(jsquery) + RETURNS int4 + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR CLASS jsquery_ops + DEFAULT FOR TYPE jsquery USING hash AS + OPERATOR 1 =, + FUNCTION 1 jsquery_hash(jsquery); + +CREATE OR REPLACE FUNCTION gin_compare_jsonb_value_path(bytea, bytea) + RETURNS integer + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_compare_partial_jsonb_value_path(bytea, bytea, smallint, internal) + RETURNS integer + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_extract_jsonb_value_path(internal, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_extract_jsonb_query_value_path(anyarray, internal, smallint, internal, internal, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_consistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal, internal) + RETURNS boolean + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_triconsistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal) + RETURNS boolean + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR CLASS jsonb_value_path_ops + FOR TYPE jsonb USING gin AS + OPERATOR 7 @>, + OPERATOR 14 @@ (jsonb, jsquery), + FUNCTION 1 gin_compare_jsonb_value_path(bytea, bytea), + FUNCTION 2 gin_extract_jsonb_value_path(internal, internal, internal), + FUNCTION 3 gin_extract_jsonb_query_value_path(anyarray, internal, smallint, internal, internal, internal, internal), + FUNCTION 4 gin_consistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal, internal), + FUNCTION 5 gin_compare_partial_jsonb_value_path(bytea, bytea, smallint, internal), + FUNCTION 6 gin_triconsistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal), + STORAGE bytea; + +CREATE OR REPLACE FUNCTION gin_compare_jsonb_path_value(bytea, bytea) + RETURNS integer + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_compare_partial_jsonb_path_value(bytea, bytea, smallint, internal) + RETURNS integer + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_extract_jsonb_path_value(internal, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_extract_jsonb_query_path_value(anyarray, internal, smallint, internal, internal, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_consistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal, internal) + RETURNS boolean + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_triconsistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal) + RETURNS boolean + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OPERATOR CLASS jsonb_path_value_ops + FOR TYPE jsonb USING gin AS + OPERATOR 7 @>, + OPERATOR 14 @@ (jsonb, jsquery), + FUNCTION 1 gin_compare_jsonb_path_value(bytea, bytea), + FUNCTION 2 gin_extract_jsonb_path_value(internal, internal, internal), + FUNCTION 3 gin_extract_jsonb_query_path_value(anyarray, internal, smallint, internal, internal, internal, internal), + FUNCTION 4 gin_consistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal, internal), + FUNCTION 5 gin_compare_partial_jsonb_path_value(bytea, bytea, smallint, internal), + FUNCTION 6 gin_triconsistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal), + STORAGE bytea; + +CREATE OR REPLACE FUNCTION gin_debug_query_value_path(jsquery) + RETURNS text + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + +CREATE OR REPLACE FUNCTION gin_debug_query_path_value(jsquery) + RETURNS text + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; diff --git a/jsquery/jsquery.control b/jsquery/jsquery.control new file mode 100644 index 0000000000..94510c82cc --- /dev/null +++ b/jsquery/jsquery.control @@ -0,0 +1,6 @@ +# jsquery extension +comment = 'data type for jsonb inspection' +default_version = '1.0' +module_pathname = '$libdir/jsquery' +relocatable = true + diff --git a/jsquery/jsquery.h b/jsquery/jsquery.h new file mode 100644 index 0000000000..d98dd6c5c4 --- /dev/null +++ b/jsquery/jsquery.h @@ -0,0 +1,249 @@ +/*------------------------------------------------------------------------- + * + * jsquery.h + * Definitions of jsquery datatype + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery.h + * + *------------------------------------------------------------------------- + */ + +#ifndef __JSQUERY_H__ +#define __JSQUERY_H__ + +#include "access/gin.h" +#include "fmgr.h" +#include "utils/numeric.h" +#include "utils/jsonb.h" + +typedef struct +{ + int32 vl_len_; /* varlena header (do not touch directly!) */ +} JsQuery; + +#define DatumGetJsQueryP(d) ((JsQuery*)DatumGetPointer(PG_DETOAST_DATUM(d))) +#define PG_GETARG_JSQUERY(x) DatumGetJsQueryP(PG_GETARG_DATUM(x)) +#define PG_RETURN_JSQUERY(p) PG_RETURN_POINTER(p) + +typedef enum JsQueryItemType { + jqiNull = jbvNull, + jqiString = jbvString, + jqiNumeric = jbvNumeric, + jqiBool = jbvBool, + jqiArray = jbvArray, + jqiAnd, + jqiOr, + jqiNot, + jqiEqual, + jqiLess, + jqiGreater, + jqiLessOrEqual, + jqiGreaterOrEqual, + jqiContains, + jqiContained, + jqiOverlap, + jqiAny, + jqiAnyArray, + jqiAnyKey, + jqiAll, + jqiAllArray, + jqiAllKey, + jqiKey, + jqiCurrent, + jqiLength, + jqiIn, + jqiIs, + jqiIndexArray +} JsQueryItemType; + +/* + * JsQueryHint is stored in the same byte as JsQueryItemType so + * JsQueryItemType should not use two high bits + */ +typedef enum JsQueryHint { + jsqIndexDefault = 0x00, + jsqForceIndex = 0x80, + jsqNoIndex = 0x40 +} JsQueryHint; + +#define JSQ_HINT_MASK (jsqIndexDefault | jsqForceIndex | jsqNoIndex) + +/* + * Support functions to parse/construct binary value. + * Unlike many other representation of expression the first/main + * node is not an operation but left operand of expression. That + * allows to implement cheep follow-path descending in jsonb + * structure and then execute operator with right operand which + * is always a constant. + */ + +typedef struct JsQueryItem { + JsQueryItemType type; + JsQueryHint hint; + int32 nextPos; + char *base; + + union { + struct { + char *data; /* for bool, numeric and string/key */ + int datalen; /* filled only for string/key */ + } value; + + struct { + int32 left; + int32 right; + } args; + + int32 arg; + + struct { + int nelems; + int current; + int32 *arrayPtr; + } array; + + uint32 arrayIndex; + }; +} JsQueryItem; + +extern void jsqInit(JsQueryItem *v, JsQuery *js); +extern void jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos); +extern bool jsqGetNext(JsQueryItem *v, JsQueryItem *a); +extern void jsqGetArg(JsQueryItem *v, JsQueryItem *a); +extern void jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a); +extern void jsqGetRightArg(JsQueryItem *v, JsQueryItem *a); +extern Numeric jsqGetNumeric(JsQueryItem *v); +extern bool jsqGetBool(JsQueryItem *v); +extern int32 jsqGetIsType(JsQueryItem *v); +extern char * jsqGetString(JsQueryItem *v, int32 *len); +extern void jsqIterateInit(JsQueryItem *v); +extern bool jsqIterateArray(JsQueryItem *v, JsQueryItem *e); + +void alignStringInfoInt(StringInfo buf); + +/* + * Parsing + */ + +typedef struct JsQueryParseItem JsQueryParseItem; + +struct JsQueryParseItem { + JsQueryItemType type; + JsQueryHint hint; + JsQueryParseItem *next; /* next in path */ + + union { + struct { + JsQueryParseItem *left; + JsQueryParseItem *right; + } args; + + JsQueryParseItem *arg; + int8 isType; /* jbv* values */ + + Numeric numeric; + bool boolean; + struct { + uint32 len; + char *val; /* could not be not null-terminated */ + } string; + + struct { + int nelems; + JsQueryParseItem **elems; + } array; + + uint32 arrayIndex; + }; +}; + +extern JsQueryParseItem* parsejsquery(const char *str, int len); + +/* jsquery_extract.c */ + +typedef enum +{ + iAny = jqiAny, + iAnyArray = jqiAnyArray, + iKey = jqiKey, + iAnyKey = jqiAnyKey, + iIndexArray = jqiIndexArray +} PathItemType; + +typedef struct PathItem PathItem; +struct PathItem +{ + PathItemType type; + int len; + int arrayIndex; + char *s; + PathItem *parent; +}; + +typedef enum +{ + eExactValue = 1, + eEmptyArray, + eInequality, + eIs, + eAny, + eAnd = jqiAnd, + eOr = jqiOr, +} ExtractedNodeType; + +typedef enum +{ + sEqual = 1, + sRange, + sInequal, + sIs, + sAny +} SelectivityClass; + +typedef struct ExtractedNode ExtractedNode; +struct ExtractedNode +{ + ExtractedNodeType type; + JsQueryHint hint; + PathItem *path; + bool indirect; + SelectivityClass sClass; + bool forceIndex; + int number; + int entryNum; + union + { + struct + { + ExtractedNode **items; + int count; + } args; + struct + { + bool leftInclusive; + bool rightInclusive; + JsQueryItem *leftBound; + JsQueryItem *rightBound; + } bounds; + JsQueryItem *exactValue; + int32 isType; + }; +}; + +typedef int (*MakeEntryHandler)(ExtractedNode *node, Pointer extra); +typedef bool (*CheckEntryHandler)(ExtractedNode *node, Pointer extra); +bool isLogicalNodeType(ExtractedNodeType type); + +ExtractedNode *extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, + CheckEntryHandler checkHandler, Pointer extra); +char *debugJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, + CheckEntryHandler checkHandler, Pointer extra); +bool queryNeedRecheck(ExtractedNode *node); +bool execRecursive(ExtractedNode *node, bool *check); +bool execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check); + +#endif diff --git a/jsquery/jsquery_constr.c b/jsquery/jsquery_constr.c new file mode 100644 index 0000000000..fcb9088758 --- /dev/null +++ b/jsquery/jsquery_constr.c @@ -0,0 +1,260 @@ +/*------------------------------------------------------------------------- + * + * jsquery_constr.c + * Functions and operations to manipulate jsquery + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_constr.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "utils/builtins.h" + +#include "jsquery.h" + +static int32 +copyJsQuery(StringInfo buf, JsQueryItem *jsq) +{ + JsQueryItem elem; + int32 next, chld; + int32 resPos = buf->len - VARHDRSZ; /* position from begining of jsquery data */ + + check_stack_depth(); + + Assert((jsq->type & jsq->hint) == 0); + Assert((jsq->type & JSQ_HINT_MASK) == 0); + + appendStringInfoChar(buf, (char)(jsq->type | jsq->hint)); + alignStringInfoInt(buf); + + next = (jsqGetNext(jsq, NULL)) ? buf->len : 0; + appendBinaryStringInfo(buf, (char*)&next /* fake value */, sizeof(next)); + + switch(jsq->type) + { + case jqiKey: + case jqiString: + { + int32 len; + char *s; + + s = jsqGetString(jsq, &len); + appendBinaryStringInfo(buf, (char*)&len, sizeof(len)); + appendBinaryStringInfo(buf, s, len + 1 /* \0 */); + } + break; + case jqiNumeric: + { + Numeric n = jsqGetNumeric(jsq); + + appendBinaryStringInfo(buf, (char*)n, VARSIZE_ANY(n)); + } + break; + case jqiBool: + { + bool v = jsqGetBool(jsq); + + appendBinaryStringInfo(buf, (char*)&v, 1); + } + break; + case jqiArray: + { + int32 i, arrayStart; + + appendBinaryStringInfo(buf, (char*)&jsq->array.nelems, + sizeof(jsq->array.nelems)); + + arrayStart = buf->len; + + /* reserve place for "pointers" to array's elements */ + for(i=0; iarray.nelems; i++) + appendBinaryStringInfo(buf, (char*)&i /* fake value */, sizeof(i)); + + while(jsqIterateArray(jsq, &elem)) + { + chld = copyJsQuery(buf, &elem); + *(int32*)(buf->data + arrayStart + i * sizeof(i)) = chld; + i++; + } + } + break; + case jqiAnd: + case jqiOr: + { + int32 leftOut, rightOut; + + leftOut = buf->len; + appendBinaryStringInfo(buf, (char*)&leftOut /* fake value */, sizeof(leftOut)); + rightOut = buf->len; + appendBinaryStringInfo(buf, (char*)&rightOut /* fake value */, sizeof(rightOut)); + + jsqGetLeftArg(jsq, &elem); + chld = copyJsQuery(buf, &elem); + *(int32*)(buf->data + leftOut) = chld; + + jsqGetRightArg(jsq, &elem); + chld = copyJsQuery(buf, &elem); + *(int32*)(buf->data + rightOut) = chld; + } + break; + case jqiEqual: + case jqiIn: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + case jqiNot: + { + int32 argOut = buf->len; + + appendBinaryStringInfo(buf, (char*)&argOut /* fake value */, sizeof(argOut)); + + jsqGetArg(jsq, &elem); + chld = copyJsQuery(buf, &elem); + *(int32*)(buf->data + argOut) = chld; + } + break; + case jqiIndexArray: + appendBinaryStringInfo(buf, (char*)&jsq->arrayIndex, + sizeof(jsq->arrayIndex)); + break; + case jqiNull: + case jqiCurrent: + case jqiLength: + case jqiAny: + case jqiAnyArray: + case jqiAnyKey: + case jqiAll: + case jqiAllArray: + case jqiAllKey: + break; + default: + elog(ERROR, "Unknown type: %d", jsq->type); + } + + if (jsqGetNext(jsq, &elem)) + *(int32*)(buf->data + next) = copyJsQuery(buf, &elem); + + return resPos; +} + +static JsQuery* +joinJsQuery(JsQueryItemType type, JsQuery *jq1, JsQuery *jq2) +{ + JsQuery *out; + StringInfoData buf; + int32 left, right, chld; + JsQueryItem v; + + initStringInfo(&buf); + enlargeStringInfo(&buf, VARSIZE_ANY(jq1) + VARSIZE_ANY(jq2) + 4 * sizeof(int32) + VARHDRSZ); + + appendStringInfoSpaces(&buf, VARHDRSZ); + + /* form jqiAnd/jqiOr header */ + appendStringInfoChar(&buf, (char)type); + alignStringInfoInt(&buf); + + /* nextPos field of header*/ + chld = 0; /* actual value, not a fake */ + appendBinaryStringInfo(&buf, (char*)&chld, sizeof(chld)); + + left = buf.len; + appendBinaryStringInfo(&buf, (char*)&left /* fake value */, sizeof(left)); + right = buf.len; + appendBinaryStringInfo(&buf, (char*)&right /* fake value */, sizeof(right)); + + /* dump left and right subtree */ + jsqInit(&v, jq1); + chld = copyJsQuery(&buf, &v); + *(int32*)(buf.data + left) = chld; + jsqInit(&v, jq2); + chld = copyJsQuery(&buf, &v); + *(int32*)(buf.data + right) = chld; + + out = (JsQuery*)buf.data; + SET_VARSIZE(out, buf.len); + + return out; +} + +PG_FUNCTION_INFO_V1(jsquery_join_and); +Datum +jsquery_join_and(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + JsQuery *out; + + out = joinJsQuery(jqiAnd, jq1, jq2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_JSQUERY(out); +} + +PG_FUNCTION_INFO_V1(jsquery_join_or); +Datum +jsquery_join_or(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + JsQuery *out; + + out = joinJsQuery(jqiOr, jq1, jq2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_JSQUERY(out); +} + +PG_FUNCTION_INFO_V1(jsquery_not); +Datum +jsquery_not(PG_FUNCTION_ARGS) +{ + JsQuery *jq = PG_GETARG_JSQUERY(0); + JsQuery *out; + StringInfoData buf; + int32 arg, chld; + JsQueryItem v; + + initStringInfo(&buf); + enlargeStringInfo(&buf, VARSIZE_ANY(jq) + 4 * sizeof(int32) + VARHDRSZ); + + appendStringInfoSpaces(&buf, VARHDRSZ); + + /* form jsquery header */ + appendStringInfoChar(&buf, (char)jqiNot); + alignStringInfoInt(&buf); + + /* nextPos field of header*/ + chld = 0; /* actual value, not a fake */ + appendBinaryStringInfo(&buf, (char*)&chld, sizeof(chld)); + + arg = buf.len; + appendBinaryStringInfo(&buf, (char*)&arg /* fake value */, sizeof(arg)); + + jsqInit(&v, jq); + chld = copyJsQuery(&buf, &v); + *(int32*)(buf.data + arg) = chld; + + out = (JsQuery*)buf.data; + SET_VARSIZE(out, buf.len); + + PG_FREE_IF_COPY(jq, 0); + + PG_RETURN_JSQUERY(out); +} + diff --git a/jsquery/jsquery_extract.c b/jsquery/jsquery_extract.c new file mode 100644 index 0000000000..01956ae0bd --- /dev/null +++ b/jsquery/jsquery_extract.c @@ -0,0 +1,1021 @@ +/*------------------------------------------------------------------------- + * + * jsquery_extract.c + * Functions and operations to support jsquery in indexes + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Alexander Korotkov + * + * IDENTIFICATION + * contrib/jsquery/jsquery_extract.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/gin.h" +#include "utils/builtins.h" +#include "utils/jsonb.h" + +#include "miscadmin.h" +#include "jsquery.h" + +static ExtractedNode *recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path); +static int coundChildren(ExtractedNode *node, ExtractedNodeType type, bool first, bool *found); +static void fillChildren(ExtractedNode *node, ExtractedNodeType type, bool first, ExtractedNode **items, int *i); +static void flatternTree(ExtractedNode *node); +static int comparePathItems(PathItem *i1, PathItem *i2); +static int compareNodes(const void *a1, const void *a2); +static int compareJsQueryItem(JsQueryItem *v1, JsQueryItem *v2); +static void processGroup(ExtractedNode *node, int start, int end); +static void simplifyRecursive(ExtractedNode *node); +static SelectivityClass getScalarSelectivityClass(ExtractedNode *node); +static ExtractedNode *makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra); +static void setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler, Pointer extra); +static void debugPath(StringInfo buf, PathItem *path); +static void debugValue(StringInfo buf, JsQueryItem *v); +static void debugRecursive(StringInfo buf, ExtractedNode *node, int shift); + +/* + * Recursive function that turns jsquery into tree of ExtractedNode items. + */ +static ExtractedNode * +recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path) +{ + ExtractedNode *leftNode, *rightNode, *result; + PathItem *pathItem; + ExtractedNodeType type; + JsQueryItem elem, e; + + e.hint = false; + check_stack_depth(); + + switch(jsq->type) + { + case jqiAnd: + case jqiOr: + type = ((jsq->type == jqiAnd) == not) ? eOr : eAnd; + + jsqGetLeftArg(jsq, &elem); + leftNode = recursiveExtract(&elem, not, false, path); + jsqGetRightArg(jsq, &elem); + rightNode = recursiveExtract(&elem, not, false, path); + + if (!leftNode || !rightNode) + { + if (type == eOr || (!leftNode && !rightNode)) + return NULL; + if (leftNode) + { + leftNode->indirect = leftNode->indirect || indirect; + return leftNode; + } + else + { + rightNode->indirect = rightNode->indirect || indirect; + return rightNode; + } + } + + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = type; + result->path = path; + result->indirect = indirect; + result->args.items = (ExtractedNode **)palloc(2 * sizeof(ExtractedNode *)); + result->args.items[0] = leftNode; + result->args.items[1] = rightNode; + result->args.count = 2; + return result; + case jqiNot: + jsqGetArg(jsq, &elem); + return recursiveExtract(&elem, !not, indirect, path); + case jqiKey: + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iKey; + pathItem->s = jsqGetString(jsq, &pathItem->len); + pathItem->parent = path; + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, indirect, pathItem); + case jqiAny: + case jqiAll: + if ((not && jsq->type == jqiAny) || (!not && jsq->type == jqiAll)) + return NULL; + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iAny; + pathItem->parent = path; + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, true, pathItem); + case jqiIndexArray: + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iIndexArray; + pathItem->arrayIndex = jsq->arrayIndex; + pathItem->parent = path; + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, true, pathItem); + case jqiAnyArray: + case jqiAllArray: + if ((not && jsq->type == jqiAnyArray) || (!not && jsq->type == jqiAllArray)) + return NULL; + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iAnyArray; + pathItem->parent = path; + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, true, pathItem); + case jqiAnyKey: + case jqiAllKey: + if ((not && jsq->type == jqiAnyKey) || (!not && jsq->type == jqiAllKey)) + return NULL; + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iAnyKey; + pathItem->parent = path; + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, true, pathItem); + case jqiCurrent: + jsqGetNext(jsq, &elem); + return recursiveExtract(&elem, not, indirect, path); + case jqiEqual: + if (not) + return NULL; + jsqGetArg(jsq, &e); + if (e.type == jqiAny) + { + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = eAny; + result->hint = jsq->hint; + result->path = path; + result->indirect = indirect; + return result; + } + else if (e.type != jqiArray) + { + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = eExactValue; + result->hint = jsq->hint; + result->path = path; + result->indirect = indirect; + result->exactValue = (JsQueryItem *)palloc(sizeof(JsQueryItem)); + *result->exactValue = e; + return result; + } + /* jqiEqual with jqiArray follows */ + case jqiIn: + case jqiOverlap: + case jqiContains: + case jqiContained: + if (not) + return NULL; + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = (jsq->type == jqiContains || jsq->type == jqiEqual) ? eAnd : eOr; + jsqGetArg(jsq, &elem); + Assert(elem.type == jqiArray); + result->path = path; + result->indirect = indirect; + result->args.items = (ExtractedNode **)palloc((elem.array.nelems + 1) * sizeof(ExtractedNode *)); + result->args.count = 0; + if (jsq->type == jqiContains || jsq->type == jqiOverlap || + jsq->type == jqiContained || jsq->type == jqiEqual) + { + pathItem = (PathItem *)palloc(sizeof(PathItem)); + pathItem->type = iAnyArray; + pathItem->parent = path; + } + else + { + pathItem = path; + } + + if (jsq->type == jqiContained || + (jsq->type == jqiEqual && elem.array.nelems == 0)) + { + ExtractedNode *item = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + + item->hint = e.hint; + item->type = eEmptyArray; + item->path = pathItem->parent; + item->indirect = false; + item->hint = jsq->hint; + + result->args.items[result->args.count] = item; + result->args.count++; + } + + while(jsqIterateArray(&elem, &e)) + { + ExtractedNode *item = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + + item->hint = e.hint; + item->type = eExactValue; + item->path = pathItem; + item->indirect = true; + item->hint = jsq->hint; + + item->exactValue = (JsQueryItem *)palloc(sizeof(JsQueryItem)); + *item->exactValue = e; + result->args.items[result->args.count] = item; + result->args.count++; + } + return result; + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + if (not) + return NULL; + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = eInequality; + result->hint = jsq->hint; + result->path = path; + result->indirect = indirect; + + if (jsq->type == jqiGreater || jsq->type == jqiGreaterOrEqual) + { + result->bounds.leftInclusive = (jsq->type == jqiGreaterOrEqual); + result->bounds.rightBound = NULL; + result->bounds.leftBound = (JsQueryItem *)palloc(sizeof(JsQueryItem)); + jsqGetArg(jsq, result->bounds.leftBound); + } + else + { + result->bounds.rightInclusive = (jsq->type == jqiLessOrEqual); + result->bounds.leftBound = NULL; + result->bounds.rightBound = (JsQueryItem *)palloc(sizeof(JsQueryItem)); + jsqGetArg(jsq, result->bounds.rightBound); + } + return result; + case jqiIs: + if (not) + return NULL; + result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); + result->type = eIs; + result->hint = jsq->hint; + result->path = path; + result->indirect = indirect; + result->isType = jsqGetIsType(jsq); + return result; + case jqiLength: + return NULL; + default: + elog(ERROR,"Wrong state: %d", jsq->type); + } + + return NULL; +} + +/* + * Count number of children connected with nodes of same type. + */ +static int +coundChildren(ExtractedNode *node, ExtractedNodeType type, + bool first, bool *found) +{ + if ((node->indirect || node->type != type) && !first) + { + return 1; + } + else + { + int i, total = 0; + if (!first) + *found = true; + for (i = 0; i < node->args.count; i++) + total += coundChildren(node->args.items[i], type, false, found); + return total; + } +} + +/* + * Fill array of children connected with nodes of same type. + */ +static void +fillChildren(ExtractedNode *node, ExtractedNodeType type, bool first, + ExtractedNode **items, int *i) +{ + if ((node->indirect || node->type != type) && !first) + { + items[*i] = node; + (*i)++; + } + else + { + int j; + for (j = 0; j < node->args.count; j++) + fillChildren(node->args.items[j], type, false, items, i); + } +} + +/* + * Turn tree into "flat" form, turning nested binary AND/OR operators into + * single n-ary AND/OR operators. + */ +static void +flatternTree(ExtractedNode *node) +{ + if (node->type == eAnd || node->type == eOr) + { + int count; + bool found = false; + + count = coundChildren(node, node->type, true, &found); + + if (found) + { + int i = 0; + ExtractedNode **items = (ExtractedNode **)palloc(count * sizeof(ExtractedNode *)); + fillChildren(node, node->type, true, items, &i); + node->args.items = items; + node->args.count = count; + } + } + if (node->type == eAnd || node->type == eOr) + { + int i; + for (i = 0; i < node->args.count; i++) + flatternTree(node->args.items[i]); + } +} + +/* + * Compare path items chains from child to parent. + */ +static int +comparePathItems(PathItem *i1, PathItem *i2) +{ + int cmp; + + if (i1 == i2) + return 0; + + if (!i1) + return -1; + if (!i2) + return 1; + + if (i1->type != i2->type) + { + return (i1->type < i2->type) ? -1 : 1; + } + + if (i1->type == iKey) + cmp = memcmp(i1->s, i2->s, Min(i1->len, i2->len)); + else + cmp = 0; + + if (cmp == 0) + { + if (i1->len != i2->len) + return (i1->len < i2->len) ? -1 : 1; + return comparePathItems(i1->parent, i2->parent); + } + else + { + return cmp; + } +} + +bool +isLogicalNodeType(ExtractedNodeType type) +{ + if (type == eAnd || type == eOr) + return true; + else + return false; +} + +/* + * Compare nodes in the order where conditions to the same fields are located + * together. + */ +static int +compareNodes(const void *a1, const void *a2) +{ + ExtractedNode *n1 = *((ExtractedNode **)a1); + ExtractedNode *n2 = *((ExtractedNode **)a2); + + if (n1->indirect != n2->indirect) + { + if (n1->indirect) + return 1; + if (n2->indirect) + return -1; + } + + if (n1->type != n2->type) + return (n1->type < n2->type) ? -1 : 1; + + if (!isLogicalNodeType(n1->type)) + { + int cmp = comparePathItems(n1->path, n2->path); + if (cmp) return cmp; + } + + if (n1->number != n2->number) + return (n1->number < n2->number) ? -1 : 1; + + return 0; +} + +/* + * Compare json values represented by JsQueryItems. + */ +static int +compareJsQueryItem(JsQueryItem *v1, JsQueryItem *v2) +{ + char *s1, *s2; + int32 len1, len2, cmp; + + if (v1->type != v2->type) + return (v1->type < v2->type) ? -1 : 1; + + switch(v1->type) + { + case jqiNull: + return 0; + case jqiString: + s1 = jsqGetString(v1, &len1); + s2 = jsqGetString(v2, &len2); + cmp = memcmp(s1, s2, Min(len1, len2)); + if (cmp != 0 || len1 == len2) + return cmp; + return (len1 < len2) ? -1 : 1; + case jqiBool: + len1 = jsqGetBool(v1); + len2 = jsqGetBool(v2); + + return (len1 - len2); + case jqiNumeric: + return DatumGetInt32(DirectFunctionCall2(numeric_cmp, + PointerGetDatum(jsqGetNumeric(v1)), + PointerGetDatum(jsqGetNumeric(v2)))); + default: + elog(ERROR, "Wrong state"); + } + + return 0; /* make compiler happy */ +} + +/* + * Process group of nodes representing conditions for the same field. After + * processing group of nodes is replaced with one node. + */ +static void +processGroup(ExtractedNode *node, int start, int end) +{ + int i; + JsQueryItem *leftBound = NULL, + *rightBound = NULL, + *exactValue = NULL; + bool leftInclusive = false, + rightInclusive = false, + first = true; + ExtractedNode *child; + ExtractedNodeType type = eAny; + JsQueryItemType isType = jqiNull; + + if (end - start < 2) + return; + + for (i = start; i < end; i++) + { + int cmp; + + child = node->args.items[i]; + + if (first || child->type <= type) + { + type = child->type; + first = false; + Assert(!isLogicalNodeType(type)); + switch(type) + { + case eAny: + case eEmptyArray: + break; + case eIs: + isType = child->isType; + break; + case eInequality: + if (child->bounds.leftBound) + { + if (!leftBound) + { + leftBound = child->bounds.leftBound; + leftInclusive = child->bounds.leftInclusive; + } + cmp = compareJsQueryItem(child->bounds.leftBound, + leftBound); + if (cmp > 0) + { + leftBound = child->bounds.leftBound; + leftInclusive = child->bounds.leftInclusive; + } + if (cmp == 0 && leftInclusive) + { + leftInclusive = child->bounds.leftInclusive; + } + } + if (child->bounds.rightBound) + { + if (!rightBound) + { + rightBound = child->bounds.rightBound; + rightInclusive = child->bounds.rightInclusive; + } + cmp = compareJsQueryItem(child->bounds.rightBound, + rightBound); + if (cmp > 0) + { + rightBound = child->bounds.rightBound; + rightInclusive = child->bounds.rightInclusive; + } + if (cmp == 0 && rightInclusive) + { + rightInclusive = child->bounds.rightInclusive; + } + } + break; + case eExactValue: + exactValue = child->exactValue; + break; + default: + elog(ERROR, "Wrong state"); + break; + + } + } + } + + child = node->args.items[start]; + child->type = type; + + switch(type) + { + case eAny: + case eEmptyArray: + break; + case eIs: + child->isType = isType; + break; + case eInequality: + child->bounds.leftBound = leftBound; + child->bounds.rightBound = rightBound; + child->bounds.leftInclusive = leftInclusive; + child->bounds.rightInclusive = rightInclusive; + break; + case eExactValue: + child->exactValue = exactValue; + break; + default: + elog(ERROR, "Wrong state"); + break; + } + + for (i = start + 1; i < end; i++) + node->args.items[i] = NULL; +} + +/* + * Reduce number of nodes in tree, by turning multiple conditions about + * same field in same context into one node. + */ +static void +simplifyRecursive(ExtractedNode *node) +{ + if (node->type == eAnd) + { + int i, groupStart = -1; + ExtractedNode *child, *prevChild = NULL; + + for (i = 0; i < node->args.count; i++) + node->args.items[i]->number = i; + + pg_qsort(node->args.items, node->args.count, + sizeof(ExtractedNode *), compareNodes); + + for (i = 0; i < node->args.count; i++) + { + child = node->args.items[i]; + if (child->indirect || isLogicalNodeType(child->type)) + break; + if (!prevChild || comparePathItems(child->path, prevChild->path) != 0) + { + if (groupStart >= 0) + processGroup(node, groupStart, i); + groupStart = i; + } + prevChild = child; + } + if (groupStart >= 0) + processGroup(node, groupStart, i); + } + + if (node->type == eAnd || node->type == eOr) + { + int i; + for (i = 0; i < node->args.count; i++) + { + if (node->args.items[i]) + simplifyRecursive(node->args.items[i]); + } + } +} + +/* + * Get selectivity class of scalar node. + */ +static SelectivityClass +getScalarSelectivityClass(ExtractedNode *node) +{ + Assert(!isLogicalNodeType(node->type)); + switch(node->type) + { + case eAny: + return sAny; + case eIs: + return sIs; + case eInequality: + if (node->bounds.leftBound && node->bounds.rightBound) + return sRange; + else + return sInequal; + case eEmptyArray: + case eExactValue: + return sEqual; + default: + elog(ERROR, "Wrong state"); + return sAny; + } +} + +/* + * Make entries for all leaf tree nodes using user-provided handler. + */ +static ExtractedNode * +makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra) +{ + if (node->type == eAnd || node->type == eOr) + { + int i, j = 0; + ExtractedNode *child; + for (i = 0; i < node->args.count; i++) + { + child = node->args.items[i]; + if (!child) continue; + if (child->sClass > node->sClass && !child->forceIndex) + { + Assert(node->type != eOr); + continue; + } + child = makeEntries(child, handler, extra); + if (child) + { + node->args.items[j] = child; + j++; + } + else if (node->type == eOr) + { + return NULL; + } + } + if (j == 1) + { + return node->args.items[0]; + } + if (j > 0) + { + node->args.count = j; + return node; + } + else + { + return NULL; + } + } + else + { + int entryNum; + + if (node->hint == jsqNoIndex) + return NULL; + + entryNum = handler(node, extra); + if (entryNum >= 0) + { + node->entryNum = entryNum; + return node; + } + else + { + return NULL; + } + } +} + +static void +setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler, + Pointer extra) +{ + int i; + bool first; + ExtractedNode *child; + + switch(node->type) + { + case eAnd: + case eOr: + first = true; + node->forceIndex = false; + for (i = 0; i < node->args.count; i++) + { + child = node->args.items[i]; + + if (!child) + continue; + + if (!isLogicalNodeType(child->type)) + { + if (child->hint == jsqNoIndex || + !checkHandler(child, extra)) + continue; + } + + setSelectivityClass(child, checkHandler, extra); + + if (child->forceIndex) + node->forceIndex = true; + + if (first) + { + node->sClass = child->sClass; + } + else + { + if (node->type == eAnd) + node->sClass = Min(node->sClass, child->sClass); + else + node->sClass = Max(node->sClass, child->sClass); + } + first = false; + } + break; + default: + node->sClass = getScalarSelectivityClass(node); + node->forceIndex = node->hint == jsqForceIndex; + break; + } +} + +/* + * Turn jsquery into tree of entries using user-provided handler. + */ +ExtractedNode * +extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, + CheckEntryHandler checkHandler, Pointer extra) +{ + ExtractedNode *root; + JsQueryItem jsq; + + jsqInit(&jsq, jq); + root = recursiveExtract(&jsq, false, false, NULL); + if (root) + { + flatternTree(root); + simplifyRecursive(root); + setSelectivityClass(root, checkHandler, extra); + root = makeEntries(root, makeHandler, extra); + } + return root; +} + +/* + * Evaluate previously extracted tree. + */ +bool +execRecursive(ExtractedNode *node, bool *check) +{ + int i; + switch(node->type) + { + case eAnd: + for (i = 0; i < node->args.count; i++) + if (!execRecursive(node->args.items[i], check)) + return false; + return true; + case eOr: + for (i = 0; i < node->args.count; i++) + if (execRecursive(node->args.items[i], check)) + return true; + return false; + default: + return check[node->entryNum]; + } +} + +/* + * Evaluate previously extracted tree using tri-state logic. + */ +bool +execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check) +{ + GinTernaryValue res, v; + int i; + + switch(node->type) + { + case eAnd: + res = GIN_TRUE; + for (i = 0; i < node->args.count; i++) + { + v = execRecursive(node->args.items[i], check); + if (v == GIN_FALSE) + return GIN_FALSE; + else if (v == GIN_MAYBE) + res = GIN_MAYBE; + } + return res; + case eOr: + res = GIN_FALSE; + for (i = 0; i < node->args.count; i++) + { + v = execRecursive(node->args.items[i], check); + if (v == GIN_TRUE) + return GIN_TRUE; + else if (v == GIN_MAYBE) + res = GIN_MAYBE; + } + return res; + default: + return check[node->entryNum]; + } +} + +/* + * Debug print of variable path. + */ +static void +debugPath(StringInfo buf, PathItem *path) +{ + if (path->parent) + { + debugPath(buf, path->parent); + appendStringInfo(buf, "."); + } + switch (path->type) + { + case jqiAny: + appendStringInfoChar(buf, '*'); + break; + case jqiAnyKey: + appendStringInfoChar(buf, '%'); + break; + case jqiAnyArray: + appendStringInfoChar(buf, '#'); + break; + case jqiIndexArray: + appendStringInfo(buf, "#%d", path->arrayIndex); + break; + case jqiKey: + appendBinaryStringInfo(buf, path->s, path->len); + break; + } +} + +/* + * Debug print of jsquery value. + */ +static void +debugValue(StringInfo buf, JsQueryItem *v) +{ + char *s; + int len; + + switch(v->type) + { + case jqiNull: + appendStringInfo(buf, "null"); + break; + case jqiString: + s = jsqGetString(v, &len); + appendStringInfo(buf, "\""); + appendBinaryStringInfo(buf, s, len); + appendStringInfo(buf, "\""); + break; + case jqiBool: + appendStringInfo(buf, jsqGetBool(v) ? "true" : "false"); + break; + case jqiNumeric: + s = DatumGetCString(DirectFunctionCall1(numeric_out, + PointerGetDatum(jsqGetNumeric(v)))); + appendStringInfoString(buf, s); + break; + default: + elog(ERROR,"Wrong type"); + break; + } +} + +static const char * +getTypeString(int32 type) +{ + switch (type) + { + case jbvArray: + return "array"; + case jbvObject: + return "object"; + case jbvString: + return "string"; + case jbvNumeric: + return "numeric"; + case jbvBool: + return "boolean"; + case jbvNull: + return "null"; + default: + elog(ERROR,"Wrong type"); + return NULL; + } +} + + +/* + * Recursive worker of debug print of query processing. + */ +static void +debugRecursive(StringInfo buf, ExtractedNode *node, int shift) +{ + int i; + + appendStringInfoSpaces(buf, shift * 2); + + if (isLogicalNodeType(node->type)) + { + appendStringInfo(buf, (node->type == eAnd) ? "AND\n" : "OR\n"); + for (i = 0; i < node->args.count; i++) + debugRecursive(buf, node->args.items[i], shift + 1); + return; + } + + debugPath(buf, node->path); + switch(node->type) + { + case eExactValue: + appendStringInfo(buf, " = "); + debugValue(buf, node->exactValue); + appendStringInfo(buf, " ,"); + break; + case eAny: + appendStringInfo(buf, " = * ,"); + break; + case eEmptyArray: + appendStringInfo(buf, " = [] ,"); + break; + case eIs: + appendStringInfo(buf, " IS %s ,", getTypeString(node->isType)); + break; + case eInequality: + if (node->bounds.leftBound) + { + if (node->bounds.leftInclusive) + appendStringInfo(buf, " >= "); + else + appendStringInfo(buf, " > "); + debugValue(buf, node->bounds.leftBound); + appendStringInfo(buf, " ,"); + } + if (node->bounds.rightBound) + { + if (node->bounds.rightInclusive) + appendStringInfo(buf, " <= "); + else + appendStringInfo(buf, " < "); + debugValue(buf, node->bounds.rightBound); + appendStringInfo(buf, " ,"); + } + break; + default: + elog(ERROR,"Wrong type"); + break; + } + appendStringInfo(buf, " entry %d \n", node->entryNum); +} + +/* + * Debug print of query processing. + */ +char * +debugJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, + CheckEntryHandler checkHandler, Pointer extra) +{ + ExtractedNode *root; + StringInfoData buf; + + root = extractJsQuery(jq, makeHandler, checkHandler, extra); + if (!root) + return "NULL\n"; + + initStringInfo(&buf); + debugRecursive(&buf, root, 0); + appendStringInfoChar(&buf, '\0'); + return buf.data; +} diff --git a/jsquery/jsquery_gram.y b/jsquery/jsquery_gram.y new file mode 100644 index 0000000000..7db9a2ded5 --- /dev/null +++ b/jsquery/jsquery_gram.y @@ -0,0 +1,364 @@ +/*------------------------------------------------------------------------- + * + * jsquery_gram.y + * Grammar definitions for jsquery datatype + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_gram.y + * + *------------------------------------------------------------------------- + */ + +%{ +#include "postgres.h" + +#include "fmgr.h" +#include "utils/builtins.h" + +#include "jsquery.h" + +/* + * Bison doesn't allocate anything that needs to live across parser calls, + * so we can easily have it use palloc instead of malloc. This prevents + * memory leaks if we error out during parsing. Note this only works with + * bison >= 2.0. However, in bison 1.875 the default is to use alloca() + * if possible, so there's not really much problem anyhow, at least if + * you're building with gcc. + */ +#define YYMALLOC palloc +#define YYFREE pfree + +/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ +#undef fprintf +#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg) + +static void +fprintf_to_ereport(const char *fmt, const char *msg) +{ + ereport(ERROR, (errmsg_internal("%s", msg))); +} + +/* struct string is shared between scan and gram */ +typedef struct string { + char *val; + int len; + int total; +} string; +#include + +/* flex 2.5.4 doesn't bother with a decl for this */ +int jsquery_yylex(YYSTYPE * yylval_param); +void jsquery_yyerror(JsQueryParseItem **result, const char *message); + +static JsQueryParseItem* +makeItemType(int type) +{ + JsQueryParseItem* v = palloc(sizeof(*v)); + + v->type = type; + v->hint = jsqIndexDefault; + v->next = NULL; + + return v; +} + +static JsQueryParseItem* +makeIndexArray(string *s) +{ + JsQueryParseItem* v = makeItemType(jqiIndexArray); + + v->arrayIndex = pg_atoi(s->val, 4, 0); + + return v; +} + +static JsQueryParseItem* +makeItemString(string *s) +{ + JsQueryParseItem *v; + + if (s == NULL) + { + v = makeItemType(jqiNull); + } + else + { + v = makeItemType(jqiString); + v->string.val = s->val; + v->string.len = s->len; + } + + return v; +} + +static JsQueryParseItem* +makeItemKey(string *s) +{ + JsQueryParseItem *v; + + v = makeItemString(s); + v->type = jqiKey; + + return v; +} + +static JsQueryParseItem* +makeItemNumeric(string *s) +{ + JsQueryParseItem *v; + + v = makeItemType(jqiNumeric); + v->numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(s->val), 0, -1)); + + return v; +} + +static JsQueryParseItem* +makeItemBool(bool val) { + JsQueryParseItem *v = makeItemType(jqiBool); + + v->boolean = val; + + return v; +} + +static JsQueryParseItem* +makeItemArray(List *list) +{ + JsQueryParseItem *v = makeItemType(jqiArray); + + v->array.nelems = list_length(list); + + if (v->array.nelems > 0) + { + ListCell *cell; + int i = 0; + + v->array.elems = palloc(sizeof(JsQueryParseItem) * v->array.nelems); + + foreach(cell, list) + v->array.elems[i++] = (JsQueryParseItem*)lfirst(cell); + } + else + { + v->array.elems = NULL; + } + + return v; +} + +static JsQueryParseItem* +makeItemBinary(int type, JsQueryParseItem* la, JsQueryParseItem *ra) +{ + JsQueryParseItem *v = makeItemType(type); + + v->args.left = la; + v->args.right = ra; + + return v; +} + +static JsQueryParseItem* +makeItemUnary(int type, JsQueryParseItem* a) +{ + JsQueryParseItem *v = makeItemType(type); + + v->arg = a; + + return v; +} + +static JsQueryParseItem* +makeItemIs(int isType) +{ + JsQueryParseItem *v = makeItemType(jqiIs); + + v->isType = isType; + + return v; +} + +static JsQueryParseItem* +makeItemList(List *list) { + JsQueryParseItem *head, *end; + ListCell *cell; + + head = end = (JsQueryParseItem*)linitial(list); + + foreach(cell, list) + { + JsQueryParseItem *c = (JsQueryParseItem*)lfirst(cell); + + if (c == head) + continue; + + end->next = c; + end = c; + } + + return head; +} + +%} + +/* BISON Declarations */ +%pure-parser +%expect 0 +%name-prefix="jsquery_yy" +%error-verbose +%parse-param {JsQueryParseItem **result} + +%union { + string str; + List *elems; /* list of JsQueryParseItem */ + + JsQueryParseItem *value; + JsQueryHint hint; +} + +%token IN_P IS_P OR_P AND_P NOT_P NULL_P TRUE_P + ARRAY_T FALSE_P NUMERIC_T OBJECT_T + STRING_T BOOLEAN_T + +%token STRING_P NUMERIC_P INT_P + +%type result scalar_value + +%type path value_list + +%type key key_any right_expr expr array numeric + +%token HINT_P + +%left OR_P +%left AND_P +%right NOT_P +%nonassoc IN_P IS_P +%nonassoc '(' ')' + +/* Grammar follows */ +%% + +result: + expr { *result = $1; } + | /* EMPTY */ { *result = NULL; } + ; + +array: + '[' value_list ']' { $$ = makeItemArray($2); } + ; + +scalar_value: + STRING_P { $$ = makeItemString(&$1); } + | IN_P { $$ = makeItemString(&$1); } + | IS_P { $$ = makeItemString(&$1); } + | OR_P { $$ = makeItemString(&$1); } + | AND_P { $$ = makeItemString(&$1); } + | NOT_P { $$ = makeItemString(&$1); } + | NULL_P { $$ = makeItemString(NULL); } + | TRUE_P { $$ = makeItemBool(true); } + | ARRAY_T { $$ = makeItemString(&$1); } + | FALSE_P { $$ = makeItemBool(false); } + | NUMERIC_T { $$ = makeItemString(&$1); } + | OBJECT_T { $$ = makeItemString(&$1); } + | STRING_T { $$ = makeItemString(&$1); } + | BOOLEAN_T { $$ = makeItemString(&$1); } + | NUMERIC_P { $$ = makeItemNumeric(&$1); } + | INT_P { $$ = makeItemNumeric(&$1); } + ; + +value_list: + scalar_value { $$ = lappend(NIL, $1); } + | value_list ',' scalar_value { $$ = lappend($1, $3); } + ; + +numeric: + NUMERIC_P { $$ = makeItemNumeric(&$1); } + | INT_P { $$ = makeItemNumeric(&$1); } + ; + +right_expr: + '=' scalar_value { $$ = makeItemUnary(jqiEqual, $2); } + | IN_P '(' value_list ')' { $$ = makeItemUnary(jqiIn, makeItemArray($3)); } + | '=' array { $$ = makeItemUnary(jqiEqual, $2); } + | '=' '*' { $$ = makeItemUnary(jqiEqual, makeItemType(jqiAny)); } + | '<' numeric { $$ = makeItemUnary(jqiLess, $2); } + | '>' numeric { $$ = makeItemUnary(jqiGreater, $2); } + | '<' '=' numeric { $$ = makeItemUnary(jqiLessOrEqual, $3); } + | '>' '=' numeric { $$ = makeItemUnary(jqiGreaterOrEqual, $3); } + | '@' '>' array { $$ = makeItemUnary(jqiContains, $3); } + | '<' '@' array { $$ = makeItemUnary(jqiContained, $3); } + | '&' '&' array { $$ = makeItemUnary(jqiOverlap, $3); } + | IS_P ARRAY_T { $$ = makeItemIs(jbvArray); } + | IS_P NUMERIC_T { $$ = makeItemIs(jbvNumeric); } + | IS_P OBJECT_T { $$ = makeItemIs(jbvObject); } + | IS_P STRING_T { $$ = makeItemIs(jbvString); } + | IS_P BOOLEAN_T { $$ = makeItemIs(jbvBool); } + ; + +expr: + path right_expr { $$ = makeItemList(lappend($1, $2)); } + | path HINT_P right_expr { $3->hint = $2; $$ = makeItemList(lappend($1, $3)); } + | NOT_P expr { $$ = makeItemUnary(jqiNot, $2); } + /* + * In next two lines NOT_P is a path actually, not a an + * logical expression. + */ + | NOT_P HINT_P right_expr { $3->hint = $2; $$ = makeItemList(lappend(lappend(NIL, makeItemKey(&$1)), $3)); } + | NOT_P right_expr { $$ = makeItemList(lappend(lappend(NIL, makeItemKey(&$1)), $2)); } + | path '(' expr ')' { $$ = makeItemList(lappend($1, $3)); } + | '(' expr ')' { $$ = $2; } + | expr AND_P expr { $$ = makeItemBinary(jqiAnd, $1, $3); } + | expr OR_P expr { $$ = makeItemBinary(jqiOr, $1, $3); } + ; + +/* + * key is always a string, not a bool or numeric + */ +key: + '*' { $$ = makeItemType(jqiAny); } + | '#' { $$ = makeItemType(jqiAnyArray); } + | '%' { $$ = makeItemType(jqiAnyKey); } + | '*' ':' { $$ = makeItemType(jqiAll); } + | '#' ':' { $$ = makeItemType(jqiAllArray); } + | '%' ':' { $$ = makeItemType(jqiAllKey); } + | '$' { $$ = makeItemType(jqiCurrent); } + | '@' '#' { $$ = makeItemType(jqiLength); } + | '#' INT_P { $$ = makeIndexArray(&$2); } + | STRING_P { $$ = makeItemKey(&$1); } + | IN_P { $$ = makeItemKey(&$1); } + | IS_P { $$ = makeItemKey(&$1); } + | OR_P { $$ = makeItemKey(&$1); } + | AND_P { $$ = makeItemKey(&$1); } + | NULL_P { $$ = makeItemKey(&$1); } + | TRUE_P { $$ = makeItemKey(&$1); } + | ARRAY_T { $$ = makeItemKey(&$1); } + | FALSE_P { $$ = makeItemKey(&$1); } + | NUMERIC_T { $$ = makeItemKey(&$1); } + | OBJECT_T { $$ = makeItemKey(&$1); } + | STRING_T { $$ = makeItemKey(&$1); } + | BOOLEAN_T { $$ = makeItemKey(&$1); } + | NUMERIC_P { $$ = makeItemKey(&$1); } + | INT_P { $$ = makeItemKey(&$1); } + ; + +/* + * NOT keyword needs separate processing + */ +key_any: + key { $$ = $$; } + | NOT_P { $$ = makeItemKey(&$1); } + ; + +path: + key { $$ = lappend(NIL, $1); } + | path '.' key_any { $$ = lappend($1, $3); } + | NOT_P '.' key_any { $$ = lappend(lappend(NIL, makeItemKey(&$1)), $3); } + ; + +%% + +#include "jsquery_scan.c" diff --git a/jsquery/jsquery_io.c b/jsquery/jsquery_io.c new file mode 100644 index 0000000000..a295244e75 --- /dev/null +++ b/jsquery/jsquery_io.c @@ -0,0 +1,403 @@ +/*------------------------------------------------------------------------- + * + * jsquery_io.c + * I/O functions for jsquery datatype + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_io.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" +#include "lib/stringinfo.h" +#include "utils/builtins.h" +#include "utils/json.h" + +#include "jsquery.h" + +PG_MODULE_MAGIC; + +static int +flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrentInPath) +{ + int32 pos = buf->len - VARHDRSZ; /* position from begining of jsquery data */ + int32 chld, next; + + check_stack_depth(); + + Assert((item->type & item->hint) == 0); + Assert((item->type & JSQ_HINT_MASK) == 0); + + appendStringInfoChar(buf, (char)(item->type | item->hint)); + alignStringInfoInt(buf); + + next = (item->next) ? buf->len : 0; + appendBinaryStringInfo(buf, (char*)&next /* fake value */, sizeof(next)); + + switch(item->type) + { + case jqiKey: + if (onlyCurrentInPath) + elog(ERROR,"Array length should be last in path"); + case jqiString: + appendBinaryStringInfo(buf, (char*)&item->string.len, sizeof(item->string.len)); + appendBinaryStringInfo(buf, item->string.val, item->string.len); + appendStringInfoChar(buf, '\0'); + break; + case jqiNumeric: + appendBinaryStringInfo(buf, (char*)item->numeric, VARSIZE(item->numeric)); + break; + case jqiBool: + appendBinaryStringInfo(buf, (char*)&item->boolean, sizeof(item->boolean)); + break; + case jqiIs: + appendBinaryStringInfo(buf, (char*)&item->isType, sizeof(item->isType)); + break; + case jqiArray: + { + int32 i, arrayStart; + + appendBinaryStringInfo(buf, (char*)&item->array.nelems, sizeof(item->array.nelems)); + arrayStart = buf->len; + + /* reserve place for "pointers" to array's elements */ + for(i=0; iarray.nelems; i++) + appendBinaryStringInfo(buf, (char*)&i /* fake value */, sizeof(i)); + + for(i=0; iarray.nelems; i++) + { + chld = flattenJsQueryParseItem(buf, item->array.elems[i], onlyCurrentInPath); + *(int32*)(buf->data + arrayStart + i * sizeof(i)) = chld; + } + + } + break; + case jqiAnd: + case jqiOr: + { + int32 left, right; + + left = buf->len; + appendBinaryStringInfo(buf, (char*)&left /* fake value */, sizeof(left)); + right = buf->len; + appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right)); + + chld = flattenJsQueryParseItem(buf, item->args.left, onlyCurrentInPath); + *(int32*)(buf->data + left) = chld; + chld = flattenJsQueryParseItem(buf, item->args.right, onlyCurrentInPath); + *(int32*)(buf->data + right) = chld; + } + break; + case jqiEqual: + case jqiIn: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + case jqiNot: + { + int32 arg; + + arg = buf->len; + appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg)); + + chld = flattenJsQueryParseItem(buf, item->arg, onlyCurrentInPath); + *(int32*)(buf->data + arg) = chld; + } + break; + case jqiIndexArray: + appendBinaryStringInfo(buf, (char*)&item->arrayIndex, + sizeof(item->arrayIndex)); + case jqiAny: + case jqiAnyArray: + case jqiAnyKey: + case jqiAll: + case jqiAllArray: + case jqiAllKey: + if (onlyCurrentInPath) + elog(ERROR,"Array length should be last in path"); + case jqiCurrent: + case jqiNull: + break; + case jqiLength: + onlyCurrentInPath = true; + break; + default: + elog(ERROR, "Unknown type: %d", item->type); + } + + if (item->next) + { + chld = flattenJsQueryParseItem(buf, item->next, onlyCurrentInPath); + *(int32*)(buf->data + next) = chld; + } + + return pos; +} + +PG_FUNCTION_INFO_V1(jsquery_in); +Datum +jsquery_in(PG_FUNCTION_ARGS) +{ + char *in = PG_GETARG_CSTRING(0); + int32 len = strlen(in); + JsQueryParseItem *jsquery = parsejsquery(in, len); + JsQuery *res; + StringInfoData buf; + + initStringInfo(&buf); + enlargeStringInfo(&buf, 4 * len /* estimation */); + + appendStringInfoSpaces(&buf, VARHDRSZ); + + if (jsquery != NULL) + { + flattenJsQueryParseItem(&buf, jsquery, false); + + res = (JsQuery*)buf.data; + SET_VARSIZE(res, buf.len); + + PG_RETURN_JSQUERY(res); + } + + PG_RETURN_NULL(); +} + +static void +printHint(StringInfo buf, JsQueryHint hint) +{ + switch(hint) + { + case jsqForceIndex: + appendStringInfoString(buf, " /*-- index */ "); + break; + case jsqNoIndex: + appendStringInfoString(buf, " /*-- noindex */ "); + break; + case jsqIndexDefault: + break; + default: + elog(ERROR, "Unknown hint: %d", hint); + } +} + +static void +printOperation(StringInfo buf, JsQueryItemType type) +{ + switch(type) + { + case jqiAnd: + appendBinaryStringInfo(buf, " AND ", 5); break; + case jqiOr: + appendBinaryStringInfo(buf, " OR ", 4); break; + case jqiEqual: + appendBinaryStringInfo(buf, " = ", 3); break; + case jqiLess: + appendBinaryStringInfo(buf, " < ", 3); break; + case jqiGreater: + appendBinaryStringInfo(buf, " > ", 3); break; + case jqiLessOrEqual: + appendBinaryStringInfo(buf, " <= ", 4); break; + case jqiGreaterOrEqual: + appendBinaryStringInfo(buf, " >= ", 4); break; + case jqiContains: + appendBinaryStringInfo(buf, " @> ", 4); break; + case jqiContained: + appendBinaryStringInfo(buf, " <@ ", 4); break; + case jqiOverlap: + appendBinaryStringInfo(buf, " && ", 4); break; + default: + elog(ERROR, "Unknown type: %d", type); + } +} + +static void +printJsQueryItem(StringInfo buf, JsQueryItem *v, bool inKey, bool printBracketes) +{ + JsQueryItem elem; + bool first = true; + + check_stack_depth(); + + printHint(buf, v->hint); + + switch(v->type) + { + case jqiNull: + appendStringInfoString(buf, "null"); + break; + case jqiKey: + if (inKey) + appendStringInfoChar(buf, '.'); + /* follow next */ + case jqiString: + escape_json(buf, jsqGetString(v, NULL)); + break; + case jqiNumeric: + appendStringInfoString(buf, + DatumGetCString(DirectFunctionCall1(numeric_out, + PointerGetDatum(jsqGetNumeric(v))))); + break; + case jqiBool: + if (jsqGetBool(v)) + appendBinaryStringInfo(buf, "true", 4); + else + appendBinaryStringInfo(buf, "false", 5); + break; + case jqiIs: + appendBinaryStringInfo(buf, " IS ", 4); + switch(jsqGetIsType(v)) + { + case jbvString: + appendBinaryStringInfo(buf, "STRING", 6); + break; + case jbvNumeric: + appendBinaryStringInfo(buf, "NUMERIC", 7); + break; + case jbvBool: + appendBinaryStringInfo(buf, "BOOLEAN", 7); + break; + case jbvArray: + appendBinaryStringInfo(buf, "ARRAY", 5); + break; + case jbvObject: + appendBinaryStringInfo(buf, "OBJECT", 6); + break; + default: + elog(ERROR, "Unknown type for IS: %d", jsqGetIsType(v)); + break; + } + break; + case jqiArray: + if (printBracketes) + appendStringInfoChar(buf, '['); + + while(jsqIterateArray(v, &elem)) + { + if (first == false) + appendBinaryStringInfo(buf, ", ", 2); + else + first = false; + printJsQueryItem(buf, &elem, false, true); + } + + if (printBracketes) + appendStringInfoChar(buf, ']'); + break; + case jqiAnd: + case jqiOr: + appendStringInfoChar(buf, '('); + jsqGetLeftArg(v, &elem); + printJsQueryItem(buf, &elem, false, true); + printOperation(buf, v->type); + jsqGetRightArg(v, &elem); + printJsQueryItem(buf, &elem, false, true); + appendStringInfoChar(buf, ')'); + break; + case jqiEqual: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + printOperation(buf, v->type); + jsqGetArg(v, &elem); + printJsQueryItem(buf, &elem, false, true); + break; + case jqiIn: + appendBinaryStringInfo(buf, " IN (", 5); + jsqGetArg(v, &elem); + printJsQueryItem(buf, &elem, false, false); + appendStringInfoChar(buf, ')'); + break; + case jqiNot: + appendBinaryStringInfo(buf, "(NOT ", 5); + jsqGetArg(v, &elem); + printJsQueryItem(buf, &elem, false, true); + appendStringInfoChar(buf, ')'); + break; + case jqiCurrent: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '$'); + break; + case jqiLength: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '@'); + appendStringInfoChar(buf, '#'); + break; + case jqiAny: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '*'); + break; + case jqiAnyArray: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '#'); + break; + case jqiAnyKey: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '%'); + break; + case jqiAll: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '*'); + appendStringInfoChar(buf, ':'); + break; + case jqiAllArray: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '#'); + appendStringInfoChar(buf, ':'); + break; + case jqiAllKey: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfoChar(buf, '%'); + appendStringInfoChar(buf, ':'); + break; + case jqiIndexArray: + if (inKey) + appendStringInfoChar(buf, '.'); + appendStringInfo(buf, "#%u", v->arrayIndex); + break; + default: + elog(ERROR, "Unknown JsQueryItem type: %d", v->type); + } + + if (jsqGetNext(v, &elem)) + printJsQueryItem(buf, &elem, true, true); +} + +PG_FUNCTION_INFO_V1(jsquery_out); +Datum +jsquery_out(PG_FUNCTION_ARGS) +{ + JsQuery *in = PG_GETARG_JSQUERY(0); + StringInfoData buf; + JsQueryItem v; + + initStringInfo(&buf); + enlargeStringInfo(&buf, VARSIZE(in) /* estimation */); + + jsqInit(&v, in); + printJsQueryItem(&buf, &v, false, true); + + PG_RETURN_CSTRING(buf.data); +} + + diff --git a/jsquery/jsquery_op.c b/jsquery/jsquery_op.c new file mode 100644 index 0000000000..a6c8864938 --- /dev/null +++ b/jsquery/jsquery_op.c @@ -0,0 +1,1009 @@ +/*------------------------------------------------------------------------- + * + * jsquery_op.c + * Functions and operations over jsquery/jsonb datatypes + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_op.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/pg_crc.h" +#if PG_VERSION_NUM >= 90500 +/* + * We have to keep same checksum algorithm as in pre-9.5 in order to be + * pg_upgradeable. + */ +#define INIT_CRC32 INIT_LEGACY_CRC32 +#define FIN_CRC32 FIN_LEGACY_CRC32 +#define COMP_CRC32 COMP_LEGACY_CRC32 +#endif + +#include "jsquery.h" + +static bool recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg); + +static int +compareNumeric(Numeric a, Numeric b) +{ + return DatumGetInt32( + DirectFunctionCall2( + numeric_cmp, + PointerGetDatum(a), + PointerGetDatum(b) + ) + ); +} + +#define jbvScalar jbvBinary +static int +JsonbType(JsonbValue *jb) +{ + int type = jb->type; + + if (jb->type == jbvBinary) + { + JsonbContainer *jbc = jb->val.binary.data; + + if (jbc->header & JB_FSCALAR) + type = jbvScalar; + else if (jbc->header & JB_FOBJECT) + type = jbvObject; + else if (jbc->header & JB_FARRAY) + type = jbvArray; + else + elog(ERROR, "Unknown container type: 0x%08x", jbc->header); + } + + return type; +} + +static bool +recursiveAny(JsQueryItem *jsq, JsonbValue *jb) +{ + bool res = false; + JsonbIterator *it; + int32 r; + JsonbValue v; + + check_stack_depth(); + + it = JsonbIteratorInit(jb->val.binary.data); + + while(res == false && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_KEY) + { + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_VALUE); + } + + if (r == WJB_VALUE || r == WJB_ELEM) + { + res = recursiveExecute(jsq, &v, NULL); + + if (res == false && v.type == jbvBinary) + res = recursiveAny(jsq, &v); + } + } + + return res; +} + +static bool +recursiveAll(JsQueryItem *jsq, JsonbValue *jb) +{ + bool res = true; + JsonbIterator *it; + int32 r; + JsonbValue v; + + check_stack_depth(); + + it = JsonbIteratorInit(jb->val.binary.data); + + while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_KEY) + { + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_VALUE); + } + + if (r == WJB_VALUE || r == WJB_ELEM) + { + if ((res = recursiveExecute(jsq, &v, NULL)) == true) + { + if (v.type == jbvBinary) + res = recursiveAll(jsq, &v); + } + + if (res == false) + break; + } + } + + return res; +} + +static bool +checkScalarEquality(JsQueryItem *jsq, JsonbValue *jb) +{ + int len; + char *s; + + if (jsq->type == jqiAny) + return true; + + if (jb->type == jbvBinary) + return false; + + if ((int)jb->type != (int)jsq->type /* see enums */) + return false; + + switch(jsq->type) + { + case jqiNull: + return true; + case jqiString: + s = jsqGetString(jsq, &len); + return (len == jb->val.string.len && memcmp(jb->val.string.val, s, len) == 0); + case jqiBool: + return (jb->val.boolean == jsqGetBool(jsq)); + case jqiNumeric: + return (compareNumeric(jsqGetNumeric(jsq), jb->val.numeric) == 0); + default: + elog(ERROR,"Wrong state"); + } + + return false; +} + +static bool +checkArrayEquality(JsQueryItem *jsq, JsonbValue *jb) +{ + int32 r; + JsonbIterator *it; + JsonbValue v; + JsQueryItem elem; + + if (!(jsq->type == jqiArray && JsonbType(jb) == jbvArray)) + return false; + + + it = JsonbIteratorInit(jb->val.binary.data); + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_BEGIN_ARRAY); + + if (v.val.array.nElems != jsq->array.nelems) + return false; + + while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r != WJB_ELEM) + continue; + + jsqIterateArray(jsq, &elem); + + if (checkScalarEquality(&elem, &v) == false) + return false; + } + + return true; +} + +static bool +checkScalarIn(JsQueryItem *jsq, JsonbValue *jb) +{ + JsQueryItem elem; + + if (jb->type == jbvBinary) + return false; + + if (jsq->type != jqiArray) + return false; + + while(jsqIterateArray(jsq, &elem)) + if (checkScalarEquality(&elem, jb)) + return true; + + return false; +} + +static bool +executeArrayOp(JsQueryItem *jsq, int32 op, JsonbValue *jb) +{ + int32 r = 0; /* keep static analyzer quiet */ + JsonbIterator *it; + JsonbValue v; + JsQueryItem elem; + + if (JsonbType(jb) != jbvArray) + return false; + if (jsq->type != jqiArray) + return false; + + if (op == jqiContains) + { + while(jsqIterateArray(jsq, &elem)) + { + bool res = false; + + it = JsonbIteratorInit(jb->val.binary.data); + + while(res == false && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_ELEM && checkScalarEquality(&elem, &v)) + res = true; + } + + if (res == false) + return false; + } + } + else + { + it = JsonbIteratorInit(jb->val.binary.data); + + while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_ELEM) + { + bool res = false; + + jsqIterateInit(jsq); + while(jsqIterateArray(jsq, &elem)) + { + if (checkScalarEquality(&elem, &v)) + { + if (op == jqiOverlap) + return true; + res = true; + break; + } + } + + if (op == jqiContained && res == false) + return false; + } + } + + if (op == jqiOverlap) + return false; + } + + return true; +} + +static bool +makeCompare(JsQueryItem *jsq, int32 op, JsonbValue *jb) +{ + int res; + + if (jb->type != jbvNumeric) + return false; + if (jsq->type != jqiNumeric) + return false; + + res = compareNumeric(jb->val.numeric, jsqGetNumeric(jsq)); + + switch(op) + { + case jqiEqual: + return (res == 0); + case jqiLess: + return (res < 0); + case jqiGreater: + return (res > 0); + case jqiLessOrEqual: + return (res <= 0); + case jqiGreaterOrEqual: + return (res >= 0); + default: + elog(ERROR, "Unknown operation"); + } + + return false; +} + +static bool +executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg) +{ + bool res = false; + /* + * read arg type + */ + Assert(jsqGetNext(jsq, NULL) == false); + Assert(jsq->type == jqiAny || jsq->type == jqiString || jsq->type == jqiNumeric || + jsq->type == jqiNull || jsq->type == jqiBool || jsq->type == jqiArray); + + if (jsqLeftArg && jsqLeftArg->type == jqiLength) + { + if (JsonbType(jb) == jbvArray || JsonbType(jb) == jbvObject) + { + int32 length; + JsonbIterator *it; + JsonbValue v; + int r; + + it = JsonbIteratorInit(jb->val.binary.data); + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT); + + length = (r == WJB_BEGIN_ARRAY) ? v.val.array.nElems : v.val.object.nPairs; + + v.type = jbvNumeric; + v.val.numeric = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(length))); + + switch(op) + { + case jqiEqual: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + res = makeCompare(jsq, op, &v); + break; + case jqiIn: + res = checkScalarIn(jsq, &v); + break; + case jqiOverlap: + case jqiContains: + case jqiContained: + break; + default: + elog(ERROR, "Unknown operation"); + } + } + } + else + { + switch(op) + { + case jqiEqual: + if (JsonbType(jb) == jbvArray && jsq->type == jqiArray) + res = checkArrayEquality(jsq, jb); + else + res = checkScalarEquality(jsq, jb); + break; + case jqiIn: + res = checkScalarIn(jsq, jb); + break; + case jqiOverlap: + case jqiContains: + case jqiContained: + res = executeArrayOp(jsq, op, jb); + break; + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + res = makeCompare(jsq, op, jb); + break; + default: + elog(ERROR, "Unknown operation"); + } + } + + return res; +} + +static bool +recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg) +{ + JsQueryItem elem; + bool res = false; + + check_stack_depth(); + + switch(jsq->type) { + case jqiAnd: + jsqGetLeftArg(jsq, &elem); + res = recursiveExecute(&elem, jb, jsqLeftArg); + if (res == true) + { + jsqGetRightArg(jsq, &elem); + res = recursiveExecute(&elem, jb, jsqLeftArg); + } + break; + case jqiOr: + jsqGetLeftArg(jsq, &elem); + res = recursiveExecute(&elem, jb, jsqLeftArg); + if (res == false) + { + jsqGetRightArg(jsq, &elem); + res = recursiveExecute(&elem, jb, jsqLeftArg); + } + break; + case jqiNot: + jsqGetArg(jsq, &elem); + res = !recursiveExecute(&elem, jb, jsqLeftArg); + break; + case jqiKey: + if (JsonbType(jb) == jbvObject) { + JsonbValue *v, key; + + key.type = jbvString; + key.val.string.val = jsqGetString(jsq, &key.val.string.len); + + v = findJsonbValueFromContainer(jb->val.binary.data, JB_FOBJECT, &key); + + if (v != NULL) + { + jsqGetNext(jsq, &elem); + res = recursiveExecute(&elem, v, NULL); + pfree(v); + } + } + break; + case jqiCurrent: + jsqGetNext(jsq, &elem); + if (JsonbType(jb) == jbvScalar) + { + JsonbIterator *it; + int32 r; + JsonbValue v; + + it = JsonbIteratorInit(jb->val.binary.data); + + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_BEGIN_ARRAY); + Assert(v.val.array.rawScalar == 1); + Assert(v.val.array.nElems == 1); + + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_ELEM); + + res = recursiveExecute(&elem, &v, jsqLeftArg); + } + else + { + res = recursiveExecute(&elem, jb, jsqLeftArg); + } + break; + case jqiAny: + jsqGetNext(jsq, &elem); + if (recursiveExecute(&elem, jb, NULL)) + res = true; + else if (jb->type == jbvBinary) + res = recursiveAny(&elem, jb); + break; + case jqiAll: + jsqGetNext(jsq, &elem); + if ((res = recursiveExecute(&elem, jb, NULL)) == true) + { + if (jb->type == jbvBinary) + res = recursiveAll(&elem, jb); + } + break; + case jqiAnyArray: + case jqiAllArray: + if (JsonbType(jb) == jbvArray) + { + JsonbIterator *it; + int32 r; + JsonbValue v; + + jsqGetNext(jsq, &elem); + it = JsonbIteratorInit(jb->val.binary.data); + + if (jsq->type == jqiAllArray) + res = true; + + while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_ELEM) + { + res = recursiveExecute(&elem, &v, NULL); + + if (jsq->type == jqiAnyArray) + { + if (res == true) + break; + } + else if (jsq->type == jqiAllArray) + { + if (res == false) + break; + } + } + } + } + break; + case jqiIndexArray: + if (JsonbType(jb) == jbvArray) + { + JsonbValue *v; + + jsqGetNext(jsq, &elem); + + v = getIthJsonbValueFromContainer(jb->val.binary.data, + jsq->arrayIndex); + + res = v && recursiveExecute(&elem, v, NULL); + } + break; + case jqiAnyKey: + case jqiAllKey: + if (JsonbType(jb) == jbvObject) + { + JsonbIterator *it; + int32 r; + JsonbValue v; + + jsqGetNext(jsq, &elem); + it = JsonbIteratorInit(jb->val.binary.data); + + if (jsq->type == jqiAllKey) + res = true; + + while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) + { + if (r == WJB_VALUE) + { + res = recursiveExecute(&elem, &v, NULL); + + if (jsq->type == jqiAnyKey) + { + if (res == true) + break; + } + else if (jsq->type == jqiAllKey) + { + if (res == false) + break; + } + } + } + } + break; + case jqiEqual: + case jqiIn: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + jsqGetArg(jsq, &elem); + res = executeExpr(&elem, jsq->type, jb, jsqLeftArg); + break; + case jqiLength: + jsqGetNext(jsq, &elem); + res = recursiveExecute(&elem, jb, jsq); + break; + case jqiIs: + if (JsonbType(jb) == jbvScalar) + { + JsonbIterator *it; + int32 r; + JsonbValue v; + + it = JsonbIteratorInit(jb->val.binary.data); + + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_BEGIN_ARRAY); + Assert(v.val.array.rawScalar == 1); + Assert(v.val.array.nElems == 1); + + r = JsonbIteratorNext(&it, &v, true); + Assert(r == WJB_ELEM); + + res = (jsqGetIsType(jsq) == JsonbType(&v)); + } + else + { + res = (jsqGetIsType(jsq) == JsonbType(jb)); + } + break; + default: + elog(ERROR,"Wrong state: %d", jsq->type); + } + + return res; +} + +PG_FUNCTION_INFO_V1(jsquery_json_exec); +Datum +jsquery_json_exec(PG_FUNCTION_ARGS) +{ + JsQuery *jq = PG_GETARG_JSQUERY(0); + Jsonb *jb = PG_GETARG_JSONB_P(1); + bool res; + JsonbValue jbv; + JsQueryItem jsq; + + jbv.type = jbvBinary; + jbv.val.binary.data = &jb->root; + jbv.val.binary.len = VARSIZE_ANY_EXHDR(jb); + + jsqInit(&jsq, jq); + + res = recursiveExecute(&jsq, &jbv, NULL); + + PG_FREE_IF_COPY(jq, 0); + PG_FREE_IF_COPY(jb, 1); + + PG_RETURN_BOOL(res); +} + +PG_FUNCTION_INFO_V1(json_jsquery_exec); +Datum +json_jsquery_exec(PG_FUNCTION_ARGS) +{ + Jsonb *jb = PG_GETARG_JSONB_P(0); + JsQuery *jq = PG_GETARG_JSQUERY(1); + bool res; + JsonbValue jbv; + JsQueryItem jsq; + + jbv.type = jbvBinary; + jbv.val.binary.data = &jb->root; + jbv.val.binary.len = VARSIZE_ANY_EXHDR(jb); + + jsqInit(&jsq, jq); + + res = recursiveExecute(&jsq, &jbv, NULL); + + PG_FREE_IF_COPY(jb, 0); + PG_FREE_IF_COPY(jq, 1); + + PG_RETURN_BOOL(res); +} + +static int +compareJsQuery(JsQueryItem *v1, JsQueryItem *v2) +{ + JsQueryItem elem1, elem2; + int32 res = 0; + + check_stack_depth(); + + if (v1->type != v2->type) + return (v1->type > v2->type) ? 1 : -1; + + switch(v1->type) + { + case jqiNull: + case jqiCurrent: + case jqiLength: + case jqiAny: + case jqiAnyArray: + case jqiAnyKey: + case jqiAll: + case jqiAllArray: + case jqiAllKey: + break; + case jqiIndexArray: + if (v1->arrayIndex != v2->arrayIndex) + res = (v1->arrayIndex > v2->arrayIndex) ? 1 : -1; + break; + case jqiKey: + case jqiString: + { + int32 len1, len2; + char *s1, *s2; + + s1 = jsqGetString(v1, &len1); + s2 = jsqGetString(v2, &len2); + + if (len1 != len2) + res = (len1 > len2) ? 1 : -1; + else + res = memcmp(s1, s2, len1); + } + break; + case jqiNumeric: + res = compareNumeric(jsqGetNumeric(v1), jsqGetNumeric(v2)); + break; + case jqiBool: + if (jsqGetBool(v1) != jsqGetBool(v2)) + res = (jsqGetBool(v1) > jsqGetBool(v2)) ? 1 : -1; + break; + case jqiArray: + if (v1->array.nelems != v2->array.nelems) + res = (v1->array.nelems > v2->array.nelems) ? 1 : -1; + + while(res == 0 && jsqIterateArray(v1, &elem1) && jsqIterateArray(v2, &elem2)) + res = compareJsQuery(&elem1, &elem2); + break; + case jqiAnd: + case jqiOr: + jsqGetLeftArg(v1, &elem1); + jsqGetLeftArg(v2, &elem2); + + res = compareJsQuery(&elem1, &elem2); + + if (res == 0) + { + jsqGetRightArg(v1, &elem1); + jsqGetRightArg(v2, &elem2); + + res = compareJsQuery(&elem1, &elem2); + } + break; + case jqiEqual: + case jqiIn: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + case jqiNot: + jsqGetArg(v1, &elem1); + jsqGetArg(v2, &elem2); + + res = compareJsQuery(&elem1, &elem2); + break; + default: + elog(ERROR, "Unknown JsQueryItem type: %d", v1->type); + } + + if (res == 0) + { + if (jsqGetNext(v1, &elem1)) + { + if (jsqGetNext(v2, &elem2)) + res = compareJsQuery(&elem1, &elem2); + else + res = 1; + } + else if (jsqGetNext(v2, &elem2)) + { + res = -1; + } + } + + return res; +} + +PG_FUNCTION_INFO_V1(jsquery_cmp); +Datum +jsquery_cmp(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_INT32(res); +} + +PG_FUNCTION_INFO_V1(jsquery_lt); +Datum +jsquery_lt(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res < 0); +} + +PG_FUNCTION_INFO_V1(jsquery_le); +Datum +jsquery_le(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res <= 0); +} + +PG_FUNCTION_INFO_V1(jsquery_eq); +Datum +jsquery_eq(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res == 0); +} + +PG_FUNCTION_INFO_V1(jsquery_ne); +Datum +jsquery_ne(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res != 0); +} + +PG_FUNCTION_INFO_V1(jsquery_ge); +Datum +jsquery_ge(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res >= 0); +} + +PG_FUNCTION_INFO_V1(jsquery_gt); +Datum +jsquery_gt(PG_FUNCTION_ARGS) +{ + JsQuery *jq1 = PG_GETARG_JSQUERY(0); + JsQuery *jq2 = PG_GETARG_JSQUERY(1); + int32 res; + JsQueryItem v1, v2; + + jsqInit(&v1, jq1); + jsqInit(&v2, jq2); + + res = compareJsQuery(&v1, &v2); + + PG_FREE_IF_COPY(jq1, 0); + PG_FREE_IF_COPY(jq2, 1); + + PG_RETURN_BOOL(res > 0); +} + +static void +hashJsQuery(JsQueryItem *v, pg_crc32 *crc) +{ + JsQueryItem elem; + + check_stack_depth(); + + COMP_CRC32(*crc, &v->type, sizeof(v->type)); + + switch(v->type) + { + case jqiNull: + COMP_CRC32(*crc, "null", 5); + break; + case jqiKey: + case jqiString: + { + int32 len; + char *s; + + s = jsqGetString(v, &len); + + if (v->type == jqiKey) + len++; /* include trailing '\0' */ + COMP_CRC32(*crc, s, len); + } + break; + case jqiNumeric: + *crc ^= (pg_crc32)DatumGetInt32(DirectFunctionCall1( + hash_numeric, + PointerGetDatum(jsqGetNumeric(v)))); + break; + case jqiBool: + { + bool b = jsqGetBool(v); + + COMP_CRC32(*crc, &b, 1); + } + break; + case jqiArray: + COMP_CRC32(*crc, &v->array.nelems, sizeof(v->array.nelems)); + while(jsqIterateArray(v, &elem)) + hashJsQuery(&elem, crc); + break; + case jqiAnd: + case jqiOr: + jsqGetLeftArg(v, &elem); + hashJsQuery(&elem, crc); + jsqGetRightArg(v, &elem); + hashJsQuery(&elem, crc); + break; + case jqiNot: + case jqiEqual: + case jqiIn: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + jsqGetArg(v, &elem); + hashJsQuery(&elem, crc); + break; + case jqiCurrent: + case jqiLength: + case jqiAny: + case jqiAnyArray: + case jqiAnyKey: + case jqiAll: + case jqiAllArray: + case jqiAllKey: + break; + case jqiIndexArray: + COMP_CRC32(*crc, &v->arrayIndex, sizeof(v->arrayIndex)); + break; + default: + elog(ERROR, "Unknown JsQueryItem type: %d", v->type); + } +} + +PG_FUNCTION_INFO_V1(jsquery_hash); +Datum +jsquery_hash(PG_FUNCTION_ARGS) +{ + JsQuery *jq = PG_GETARG_JSQUERY(0); + JsQueryItem v; + pg_crc32 res; + + INIT_CRC32(res); + jsqInit(&v, jq); + hashJsQuery(&v, &res); + FIN_CRC32(res); + + PG_FREE_IF_COPY(jq, 0); + + PG_RETURN_INT32(res); +} + diff --git a/jsquery/jsquery_scan.l b/jsquery/jsquery_scan.l new file mode 100644 index 0000000000..e73bdd7f10 --- /dev/null +++ b/jsquery/jsquery_scan.l @@ -0,0 +1,508 @@ +/*------------------------------------------------------------------------- + * + * jsquery_scan.l + * Lexical parser for jsquery datatype + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_scan.l + * + *------------------------------------------------------------------------- + */ + +%{ +#include "mb/pg_wchar.h" + +static string scanstring; + +/* No reason to constrain amount of data slurped */ +/* #define YY_READ_BUF_SIZE 16777216 */ + +/* Handles to the buffer that the lexer uses internally */ +static YY_BUFFER_STATE scanbufhandle; +static char *scanbuf; +static int scanbuflen; + +static void addstring(bool init, char *s, int l); +static void addchar(bool init, char s); +static int checkSpecialVal(void); /* examine scanstring for the special value */ +static JsQueryHint checkHint(void); + +static void parseUnicode(char *s, int l); + +%} + +%option 8bit +%option never-interactive +%option nodefault +%option noinput +%option nounput +%option noyywrap +%option warn +%option prefix="jsquery_yy" +%option bison-bridge + +%x xQUOTED +%x xNONQUOTED +%x xCOMMENT + +special [\%\$\.\[\]\(\)\|\&\!\=\<\>\@\#\,\*:] +any [^\%\$\.\[\]\(\)\|\&\!\=\<\>\@\#\,\* \t\n\r\f\\\"\/:] +blank [ \t\n\r\f] +unicode \\u[0-9A-Fa-f]{4} + +%% + +{special} { return *yytext; } + +{blank}+ { /* ignore */ } + +\/\* { + addchar(true, '\0'); + BEGIN xCOMMENT; + } + +[+-]?[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+ /* float */ { + addstring(true, yytext, yyleng); + addchar(false, '\0'); + yylval->str = scanstring; + return NUMERIC_P; + } + +[+-]?\.[0-9]+[eE][+-]?[0-9]+ /* float */ { + addstring(true, yytext, yyleng); + addchar(false, '\0'); + yylval->str = scanstring; + return NUMERIC_P; + } + +[+-]?([0-9]+)?\.[0-9]+ { + addstring(true, yytext, yyleng); + addchar(false, '\0'); + yylval->str = scanstring; + return NUMERIC_P; + } + +[+-][0-9]+ { + addstring(true, yytext, yyleng); + addchar(false, '\0'); + yylval->str = scanstring; + return NUMERIC_P; + } + +[0-9]+ { + addstring(true, yytext, yyleng); + addchar(false, '\0'); + yylval->str = scanstring; + return INT_P; + } + +{any}+ { + addstring(true, yytext, yyleng); + BEGIN xNONQUOTED; + } + +\" { + addchar(true, '\0'); + BEGIN xQUOTED; + } + +\\ { + yyless(0); + addchar(true, '\0'); + BEGIN xNONQUOTED; + } + +{any}+ { + addstring(false, yytext, yyleng); + } + +{blank}+ { + yylval->str = scanstring; + BEGIN INITIAL; + return checkSpecialVal(); + } + + +\/\* { + yylval->str = scanstring; + addchar(true, '\0'); + BEGIN xCOMMENT; + return checkSpecialVal(); + } + + +\/ { addchar(false, '/'); } + +({special}|\") { + yylval->str = scanstring; + yyless(0); + BEGIN INITIAL; + return checkSpecialVal(); + } + +<> { + yylval->str = scanstring; + BEGIN INITIAL; + return checkSpecialVal(); + } + +\\[\"\\] { addchar(false, yytext[1]); } + +\\b { addchar(false, '\b'); } + +\\f { addchar(false, '\f'); } + +\\n { addchar(false, '\n'); } + +\\r { addchar(false, '\r'); } + +\\t { addchar(false, '\t'); } + +{unicode}+ { parseUnicode(yytext, yyleng); } + +\\u { yyerror(NULL, "Unicode sequence is invalid"); } + +\\. { yyerror(NULL, "Escape sequence is invalid"); } + +\\ { yyerror(NULL, "Unexpected end after backslesh"); } + +<> { yyerror(NULL, "Unexpected end of quoted string"); } + +\" { + yylval->str = scanstring; + BEGIN INITIAL; + return STRING_P; + } + +[^\\\"]+ { addstring(false, yytext, yyleng); } + +<> { yyterminate(); } + +\*\/ { + BEGIN INITIAL; + + if ((yylval->hint = checkHint()) != jsqIndexDefault) + return HINT_P; + } + +[^\*]+ { addstring(false, yytext, yyleng); } + +\* { addchar(false, '*'); } + +<> { yyerror(NULL, "Unexpected end of comment"); } + +%% + +void +yyerror(JsQueryParseItem **result, const char *message) +{ + if (*yytext == YY_END_OF_BUFFER_CHAR) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad jsquery representation"), + /* translator: %s is typically "syntax error" */ + errdetail("%s at end of input", message))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad jsquery representation"), + /* translator: first %s is typically "syntax error" */ + errdetail("%s at or near \"%s\"", message, yytext))); + } +} + +typedef struct keyword +{ + int16 len; + bool lowercase; + int val; + char *keyword; +} keyword; + +/* + * Array of key words should be sorted by length and then + * alphabetical order + */ + +static keyword keywords[] = { + { 2, false, IN_P, "in"}, + { 2, false, IS_P, "is"}, + { 2, false, OR_P, "or"}, + { 3, false, AND_P, "and"}, + { 3, false, NOT_P, "not"}, + { 4, true, NULL_P, "null"}, + { 4, true, TRUE_P, "true"}, + { 5, false, ARRAY_T, "array"}, + { 5, true, FALSE_P, "false"}, + { 6, false, OBJECT_T, "object"}, + { 6, false, STRING_T, "string"}, + { 7, false, BOOLEAN_T, "boolean"}, + { 7, false, NUMERIC_T, "numeric"} +}; + +static int +checkSpecialVal() +{ + int res = STRING_P; + int diff; + keyword *StopLow = keywords, + *StopHigh = keywords + lengthof(keywords), + *StopMiddle; + + if (scanstring.len > keywords[lengthof(keywords) - 1].len) + return res; + + while(StopLow < StopHigh) + { + StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); + + if (StopMiddle->len == scanstring.len) + diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val, scanstring.len); + else + diff = StopMiddle->len - scanstring.len; + + if (diff < 0) + StopLow = StopMiddle + 1; + else if (diff > 0) + StopHigh = StopMiddle; + else + { + if (StopMiddle->lowercase) + diff = strncmp(StopMiddle->keyword, scanstring.val, scanstring.len); + + if (diff == 0) + res = StopMiddle->val; + + break; + } + } + + return res; +} + +static JsQueryHint +checkHint() +{ + if (scanstring.len <= 2 || strncmp(scanstring.val, "--", 2) != 0) + return jsqIndexDefault; + + scanstring.val += 2; + scanstring.len -= 2; + + while(scanstring.len > 0 && isspace(*scanstring.val)) + { + scanstring.val++; + scanstring.len--; + } + + if (scanstring.len >= 5 && pg_strncasecmp(scanstring.val, "index", 5) == 0) + return jsqForceIndex; + + if (scanstring.len >= 7 && pg_strncasecmp(scanstring.val, "noindex", 7) == 0) + return jsqNoIndex; + + return jsqIndexDefault; +} +/* + * Called before any actual parsing is done + */ +static void +jsquery_scanner_init(const char *str, int slen) +{ + if (slen <= 0) + slen = strlen(str); + + /* + * Might be left over after ereport() + */ + if (YY_CURRENT_BUFFER) + yy_delete_buffer(YY_CURRENT_BUFFER); + + /* + * Make a scan buffer with special termination needed by flex. + */ + + scanbuflen = slen; + scanbuf = palloc(slen + 2); + memcpy(scanbuf, str, slen); + scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; + scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + + BEGIN(INITIAL); +} + + +/* + * Called after parsing is done to clean up after jsquery_scanner_init() + */ +static void +jsquery_scanner_finish(void) +{ + yy_delete_buffer(scanbufhandle); + pfree(scanbuf); +} + +static void +addstring(bool init, char *s, int l) { + if (init) { + scanstring.total = 32; + scanstring.val = palloc(scanstring.total); + scanstring.len = 0; + } + + if (s && l) { + while(scanstring.len + l + 1 >= scanstring.total) { + scanstring.total *= 2; + scanstring.val = repalloc(scanstring.val, scanstring.total); + } + + memcpy(scanstring.val + scanstring.len, s, l); + scanstring.len += l; + } +} + +static void +addchar(bool init, char s) { + if (init) + { + scanstring.total = 32; + scanstring.val = palloc(scanstring.total); + scanstring.len = 0; + } + else if(scanstring.len + 1 >= scanstring.total) + { + scanstring.total *= 2; + scanstring.val = repalloc(scanstring.val, scanstring.total); + } + + scanstring.val[ scanstring.len ] = s; + if (s != '\0') + scanstring.len++; +} + +JsQueryParseItem* +parsejsquery(const char *str, int len) { + JsQueryParseItem *parseresult; + + jsquery_scanner_init(str, len); + + if (jsquery_yyparse((void*)&parseresult) != 0) + jsquery_yyerror(NULL, "bugus input"); + + jsquery_scanner_finish(); + + return parseresult; +} + +static int +hexval(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 0xA; + if (c >= 'A' && c <= 'F') + return c - 'A' + 0xA; + elog(ERROR, "invalid hexadecimal digit"); + return 0; /* not reached */ +} + +/* + * parseUnicode was adopted from json_lex_string() in + * src/backend/utils/adt/json.c + */ +static void +parseUnicode(char *s, int l) +{ + int i, j; + int ch = 0; + int hi_surrogate = -1; + + Assert(l % 6 /* \uXXXX */ == 0); + + for(i = 0; i < l / 6; i++) + { + ch = 0; + + for(j=0; j<4; j++) + ch = (ch << 4) | hexval(s[ i*6 + 2 + j]); + + if (ch >= 0xd800 && ch <= 0xdbff) + { + if (hi_surrogate != -1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type jsquery"), + errdetail("Unicode high surrogate must not follow a high surrogate."))); + hi_surrogate = (ch & 0x3ff) << 10; + continue; + } + else if (ch >= 0xdc00 && ch <= 0xdfff) + { + if (hi_surrogate == -1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type jsquery"), + errdetail("Unicode low surrogate must follow a high surrogate."))); + ch = 0x10000 + hi_surrogate + (ch & 0x3ff); + hi_surrogate = -1; + } + + if (hi_surrogate != -1) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type jsquery"), + errdetail("Unicode low surrogate must follow a high surrogate."))); + + /* + * For UTF8, replace the escape sequence by the actual + * utf8 character in lex->strval. Do this also for other + * encodings if the escape designates an ASCII character, + * otherwise raise an error. + */ + + if (ch == 0) + { + /* We can't allow this, since our TEXT type doesn't */ + ereport(ERROR, + (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), + errmsg("unsupported Unicode escape sequence"), + errdetail("\\u0000 cannot be converted to text."))); + } + else if (GetDatabaseEncoding() == PG_UTF8) + { + char utf8str[5]; + int utf8len; + + unicode_to_utf8(ch, (unsigned char *) utf8str); + utf8len = pg_utf_mblen((unsigned char *) utf8str); + addstring(false, utf8str, utf8len); + } + else if (ch <= 0x007f) + { + /* + * This is the only way to designate things like a + * form feed character in JSON, so it's useful in all + * encodings. + */ + addchar(false, (char) ch); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type jsquery"), + errdetail("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."))); + } + + hi_surrogate = -1; + } +} + + diff --git a/jsquery/jsquery_support.c b/jsquery/jsquery_support.c new file mode 100644 index 0000000000..ee63c8c76c --- /dev/null +++ b/jsquery/jsquery_support.c @@ -0,0 +1,251 @@ +/*------------------------------------------------------------------------- + * + * jsquery_support.c + * Functions and operations to support jsquery + * + * Copyright (c) 2014, PostgreSQL Global Development Group + * Author: Teodor Sigaev + * + * IDENTIFICATION + * contrib/jsquery/jsquery_support.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "jsquery.h" + +#define read_byte(v, b, p) do { \ + (v) = *(uint8*)((b) + (p)); \ + (p) += 1; \ +} while(0) \ + +#define read_int32(v, b, p) do { \ + (v) = *(uint32*)((b) + (p)); \ + (p) += sizeof(int32); \ +} while(0) \ + +void +alignStringInfoInt(StringInfo buf) +{ + switch(INTALIGN(buf->len) - buf->len) + { + case 3: + appendStringInfoCharMacro(buf, 0); + case 2: + appendStringInfoCharMacro(buf, 0); + case 1: + appendStringInfoCharMacro(buf, 0); + default: + break; + } +} + +void +jsqInit(JsQueryItem *v, JsQuery *js) +{ + jsqInitByBuffer(v, VARDATA(js), 0); +} + +void +jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos) +{ + v->base = base; + + read_byte(v->type, base, pos); + + v->hint = v->type & JSQ_HINT_MASK; + v->type &= ~JSQ_HINT_MASK; + + switch(INTALIGN(pos) - pos) + { + case 3: pos++; + case 2: pos++; + case 1: pos++; + default: break; + } + + read_int32(v->nextPos, base, pos); + + switch(v->type) + { + case jqiNull: + case jqiCurrent: + case jqiLength: + case jqiAny: + case jqiAnyArray: + case jqiAnyKey: + case jqiAll: + case jqiAllArray: + case jqiAllKey: + break; + case jqiIndexArray: + read_int32(v->arrayIndex, base, pos); + break; + case jqiKey: + case jqiString: + read_int32(v->value.datalen, base, pos); + /* follow next */ + case jqiNumeric: + case jqiBool: + case jqiIs: + v->value.data = base + pos; + break; + case jqiArray: + read_int32(v->array.nelems, base, pos); + v->array.current = 0; + v->array.arrayPtr = (int32*)(base + pos); + break; + case jqiAnd: + case jqiOr: + read_int32(v->args.left, base, pos); + read_int32(v->args.right, base, pos); + break; + case jqiEqual: + case jqiLess: + case jqiGreater: + case jqiLessOrEqual: + case jqiGreaterOrEqual: + case jqiContains: + case jqiContained: + case jqiOverlap: + case jqiIn: + case jqiNot: + read_int32(v->arg, base, pos); + break; + default: + abort(); + elog(ERROR, "Unknown type: %d", v->type); + } +} + +void +jsqGetArg(JsQueryItem *v, JsQueryItem *a) +{ + Assert( + v->type == jqiEqual || + v->type == jqiLess || + v->type == jqiGreater || + v->type == jqiLessOrEqual || + v->type == jqiGreaterOrEqual || + v->type == jqiContains || + v->type == jqiContained || + v->type == jqiOverlap || + v->type == jqiIn || + v->type == jqiNot + ); + + jsqInitByBuffer(a, v->base, v->arg); +} + +bool +jsqGetNext(JsQueryItem *v, JsQueryItem *a) +{ + if (v->nextPos > 0) + { + Assert( + v->type == jqiKey || + v->type == jqiAny || + v->type == jqiIndexArray || + v->type == jqiAnyArray || + v->type == jqiAnyKey || + v->type == jqiAll || + v->type == jqiAllArray || + v->type == jqiAllKey || + v->type == jqiCurrent || + v->type == jqiLength + ); + + if (a) + jsqInitByBuffer(a, v->base, v->nextPos); + return true; + } + + return false; +} + +void +jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a) +{ + Assert( + v->type == jqiAnd || + v->type == jqiOr + ); + + jsqInitByBuffer(a, v->base, v->args.left); +} + +void +jsqGetRightArg(JsQueryItem *v, JsQueryItem *a) +{ + Assert( + v->type == jqiAnd || + v->type == jqiOr + ); + + jsqInitByBuffer(a, v->base, v->args.right); +} + +bool +jsqGetBool(JsQueryItem *v) +{ + Assert(v->type == jqiBool); + + return (bool)*v->value.data; +} + +Numeric +jsqGetNumeric(JsQueryItem *v) +{ + Assert(v->type == jqiNumeric); + + return (Numeric)v->value.data; +} + +int32 +jsqGetIsType(JsQueryItem *v) +{ + Assert(v->type = jqiIs); + + return (int32)*v->value.data; +} + +char* +jsqGetString(JsQueryItem *v, int32 *len) +{ + Assert( + v->type == jqiKey || + v->type == jqiString + ); + + if (len) + *len = v->value.datalen; + return v->value.data; +} + +void +jsqIterateInit(JsQueryItem *v) +{ + Assert(v->type == jqiArray); + + v->array.current = 0; +} + +bool +jsqIterateArray(JsQueryItem *v, JsQueryItem *e) +{ + Assert(v->type == jqiArray); + + if (v->array.current < v->array.nelems) + { + jsqInitByBuffer(e, v->base, v->array.arrayPtr[v->array.current]); + v->array.current++; + return true; + } + else + { + return false; + } +} + diff --git a/jsquery/sql/jsquery.sql b/jsquery/sql/jsquery.sql new file mode 100644 index 0000000000..d264955adb --- /dev/null +++ b/jsquery/sql/jsquery.sql @@ -0,0 +1,548 @@ +CREATE EXTENSION jsquery; + +set escape_string_warning=off; +set standard_conforming_strings=on; + +CREATE TABLE test_jsquery (v jsonb); + +\copy test_jsquery from 'data/test_jsquery.data' + +select 'asd.zzz = 13'::jsquery; +select 'asd.zzz < 13'::jsquery; +select 'asd(zzz < 13)'::jsquery; +select 'asd(zzz < 13 AND x = true)'::jsquery; +select 'asd(zzz < 13 AND x = "true")'::jsquery; +select 'asd(zzz < 13 AND x.zxc = "true")'::jsquery; +select 'asd(zzz < 13 OR #.zxc = "true" /* test */)'::jsquery; +select 'asd(* < 13 AND /* ttt */ #.zxc = "true")'::jsquery; +select '(* < 13 AND #.zxc = "true")'::jsquery; +select '* < 13 AND #.zxc/* t2 */ = "true"'::jsquery; +select '* < 13 AND #.zxc"x" = "true"'::jsquery; + +select 'a < 1'::jsquery; +select 'a < -1'::jsquery; +select 'a < +1'::jsquery; +select 'a < .1'::jsquery; +select 'a < -.1'::jsquery; +select 'a < +.1'::jsquery; +select 'a < 0.1'::jsquery; +select 'a < -0.1'::jsquery; +select 'a < +0.1'::jsquery; +select 'a < 10.1'::jsquery; +select 'a < -10.1'::jsquery; +select 'a < +10.1'::jsquery; +select 'a < 1e1'::jsquery; +select 'a < -1e1'::jsquery; +select 'a < +1e1'::jsquery; +select 'a < .1e1'::jsquery; +select 'a < -.1e1'::jsquery; +select 'a < +.1e1'::jsquery; +select 'a < 0.1e1'::jsquery; +select 'a < -0.1e1'::jsquery; +select 'a < +0.1e1'::jsquery; +select 'a < 10.1e1'::jsquery; +select 'a < -10.1e1'::jsquery; +select 'a < +10.1e1'::jsquery; +select 'a < 1e-1'::jsquery; +select 'a < -1e-1'::jsquery; +select 'a < +1e-1'::jsquery; +select 'a < .1e-1'::jsquery; +select 'a < -.1e-1'::jsquery; +select 'a < +.1e-1'::jsquery; +select 'a < 0.1e-1'::jsquery; +select 'a < -0.1e-1'::jsquery; +select 'a < +0.1e-1'::jsquery; +select 'a < 10.1e-1'::jsquery; +select 'a < -10.1e-1'::jsquery; +select 'a < +10.1e-1'::jsquery; +select 'a < 1e+1'::jsquery; +select 'a < -1e+1'::jsquery; +select 'a < +1e+1'::jsquery; +select 'a < .1e+1'::jsquery; +select 'a < -.1e+1'::jsquery; +select 'a < +.1e+1'::jsquery; +select 'a < 0.1e+1'::jsquery; +select 'a < -0.1e+1'::jsquery; +select 'a < +0.1e+1'::jsquery; +select 'a < 10.1e+1'::jsquery; +select 'a < -10.1e+1'::jsquery; +select 'a < +10.1e+1'::jsquery; + +select 'a in (0,1,2)'::jsquery; +select 'a IN (0,null, "null", xxx, "zzz", 2)'::jsquery; + +select 'not < 1'::jsquery; +select 'not not < 1'::jsquery; +select 'not( not < 1)'::jsquery; +select 'not.x < 1'::jsquery; +select 'x.not < 1'::jsquery; +select 'a.%(not x > 0 and not (y < 0 or z = 0))'::jsquery; + +select 'is < 1'::jsquery; +select 'in < 1'::jsquery; + +select 'not is < 1'::jsquery; +select 'not in < 1'::jsquery; + +select 'in in (1,2)'::jsquery; +select 'is in (1,2)'::jsquery; +select 'not in (1,2)'::jsquery; + +select 'in is numeric'::jsquery; +select 'is is numeric'::jsquery; +select 'not is numeric'::jsquery; + +select 'not.in < 1'::jsquery; +select 'not.is < 1'::jsquery; +select 'not.not < 1'::jsquery; +select 'in.in < 1'::jsquery; +select 'in.is < 1'::jsquery; +select 'in.not < 1'::jsquery; +select 'is.in < 1'::jsquery; +select 'is.is < 1'::jsquery; +select 'is.not < 1'::jsquery; + +select 'a.b.#4 > 4'::jsquery; +select 'a.b.#10203.* > 4'::jsquery; + +select '{"a": {"b": null}}'::jsonb @@ 'a.b = 1'; +select '{"a": {"b": null}}'::jsonb @@ 'a.b = null'; +select '{"a": {"b": null}}'::jsonb @@ 'a.b = false'; +select '{"a": {"b": false}}'::jsonb @@ 'a.b = false'; +select '{"a": {"b": false}}'::jsonb @@ 'a.b = true'; +select '{"a": {"b": true}}'::jsonb @@ 'a.b = true'; + + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 1'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 1'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 1'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 1'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 1'; + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 2'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 2'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 2'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 2'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 2'; + +select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 0'; + +select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; +select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; +select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 1 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1,2,3,4 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1,2,3,4 ]'; + +select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 4'; +select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 3'; + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a = 4'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a = 4'; + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 1 OR a=3)'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 OR a=1)'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=1)'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=2)' as "false"; +select '[{"a": 2, "b":3}, {"a": 3, "b": 1}]'::jsonb @@ '#(b = 1 and a=3)'; + +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a.a = 4'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a.a = 4'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.#.a.a = 4'; +select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.*.a.a = 4'; + +select '{"a": 1}'::jsonb @@ 'a in (0,1,2)'; +select '{"a": 1}'::jsonb @@ 'a in (0,2)'; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#=2'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 5 ]'; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a=*'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b=*'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.c=*'; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b = [1,2,3]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# = [1,2,3]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b && [1,2,3]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# && [1,2,3]'; + +select 'asd.# = 3'::jsquery & 'zzz = true' | 'xxx.# = zero'; +select !'asd.# = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; +select !'asd.#3.f = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; + +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0]'::jsquery; +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,1]'::jsquery; +select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,3]'::jsquery; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 2 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b($ && [ 2 ])'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b && [ 2 ]'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b ($ && [ 2 ])'; + +select '[1,2,3]'::jsonb @@ '# && [2]'; +select '[1,2,3]'::jsonb @@ '#($ && [2])'; +select '[1,2,3]'::jsonb @@ '$ && [2]'; +select '[1,2,3]'::jsonb @@ '$ ($ && [2])'; +select '[1,2,3]'::jsonb @@ '$ = 2'; +select '[1,2,3]'::jsonb @@ '# = 2'; +select '[1,2,3]'::jsonb @@ '#.$ = 2'; +select '[1,2,3]'::jsonb @@ '#($ = 2)'; + +select '[3,4]'::jsonb @@ '#($ > 2 and $ < 5)'; +select '[3,4]'::jsonb @@ '# > 2 and # < 5'; +select '[1,6]'::jsonb @@ '#($ > 2 and $ < 5)'; +select '[1,6]'::jsonb @@ '# > 2 and # < 5'; + +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.b=3'; +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ 'a.%=3'; +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.%="hey"'; +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%="hey"'; +select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%=[5,6]'; + +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#1 = 2'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#2 = 2'; +select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#3 = 2'; +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#1.x = 2'; +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#2.x = 2'; +select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#3.x = 2'; + +select '"XXX"'::jsonb @@ '$="XXX"'; +select '"XXX"'::jsonb @@ '#.$="XXX"'; + +--Unicode + +select 'a\t = "dollar \u0024 character"'::jsquery; +select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar \u0024 character"'; +select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar $ character"'; +select '{ "a": "dollar $ character" }'::jsonb @@ '* = "dollar \u0024 character"'; +select 'a\r = "\n\""'::jsquery; +select 'a\r = "\u0000"'::jsquery; +select 'a\r = \u0000'::jsquery; +select 'a\r = "\abcd"'::jsquery AS err; +select 'a\r = "\\abcd"'::jsquery; +select 'a\r = "x\u0000"'::jsquery; +select 'a\r = x\u0000'::jsquery; +select 'a\r = "x\abcd"'::jsquery AS err; +select 'a\r = "x\\abcd"'::jsquery; +select 'a\r = "x\u0000x"'::jsquery; +select 'a\r = x\u0000x'::jsquery; +select 'a\r = "x\abcdx"'::jsquery AS err; +select 'a\r = "x\\abcdx"'::jsquery; +select 'a\r = "\u0000x"'::jsquery; +select 'a\r = \u0000x'::jsquery; +select 'a\r = "\abcdx"'::jsquery AS err; +select 'a\r = "\\abcdx"'::jsquery; +select 'a\r = x"\\abcd"'::jsquery AS err; + +--IS + +select 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric OR as is string'::jsquery; +select '{"as": "xxx"}' @@ 'as IS string'::jsquery; +select '{"as": "xxx"}' @@ 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric'::jsquery; +select '{"as": 5}' @@ 'as is Numeric'::jsquery; +select '{"as": true}' @@ 'as is boolean'::jsquery; +select '{"as": false}' @@ 'as is boolean'::jsquery; +select '{"as": "false"}' @@ 'as is boolean'::jsquery; +select '["xxx"]' @@ '$ IS array'::jsquery; +select '{"as": false}' @@ '$ IS object'::jsquery; +select '"xxx"' @@ '$ IS string'::jsquery; +select '"xxx"' @@ '$ IS numeric'::jsquery; + +--hint + +select 'a /*-- noindex */ = 5'::jsquery; +select 'a /*-- index */ = 5'::jsquery; +select 'asd.# = 3'::jsquery & 'zzz /*-- noindex */ = true' | 'xxx.# /*-- index */ = zero'; +select 'a /*-- xxx */ = 5'::jsquery; +select 'a /* index */ = 5'::jsquery; +select 'a /* noindex */ = 5'::jsquery; +select 'a = /*-- noindex */ 5'::jsquery; +select 'a = /* noindex */ 5'::jsquery; + +--LENGTH +select 'a.@# = 4'::jsquery; +select 'a.@#.$ = 4'::jsquery as noerror; +select 'a.@#.a = 4'::jsquery as error; +select 'a.@#.* = 4'::jsquery as error; +select 'a.@#.% = 4'::jsquery as error; +select 'a.@#.# = 4'::jsquery as error; +select 'a.@#.*: = 4'::jsquery as error; +select 'a.@#.%: = 4'::jsquery as error; +select 'a.@#.#: = 4'::jsquery as error; +select 'a.@# (a = 5 or b = 6)'::jsquery as error; +select '[]' @@ '@# = 0'::jsquery; +select '[]' @@ '@# < 2'::jsquery; +select '[]' @@ '@# > 1'::jsquery; +select '[1]' @@ '@# = 0'::jsquery; +select '[1]' @@ '@# < 2'::jsquery; +select '[1]' @@ '@# > 1'::jsquery; +select '[1,2]' @@ '@# = 0'::jsquery; +select '[1,2]' @@ '@# < 2'::jsquery; +select '[1,2]' @@ '@# > 1'::jsquery; +select '[1,2]' @@ '@# in (1, 2)'::jsquery; +select '[1,2]' @@ '@# in (1, 3)'::jsquery; +select '{"a":[1,2]}' @@ '@# in (2, 4)'::jsquery; +select '{"a":[1,2]}' @@ 'a.@# in (2, 4)'::jsquery; +select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery; +select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery; +select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery; +select '{"a":[1,2]}' @@ '@# = 1'::jsquery; + +--ALL +select 'a.*: = 4'::jsquery; +select '%: = 4'::jsquery; +select '#:.i = 4'::jsquery; +select '[]' @@ '#: ($ > 1 and $ < 5)'::jsquery; +select '[2,3,4]' @@ '#: ($ > 1 and $ < 5)'::jsquery; +select '[2,3,5]' @@ '#: ($ > 1 and $ < 5)'::jsquery; +select '[2,3,5]' @@ '# ($ > 1 and $ < 5)'::jsquery; +select '[2,3,"x"]' @@ '#: ($ > 1 and $ < 5)'::jsquery; +select '{}' @@ '%: ($ > 1 and $ < 5)'::jsquery; +select '{}' @@ '*: ($ is object)'::jsquery; +select '"a"' @@ '*: is string'::jsquery; +select '1' @@ '*: is string'::jsquery; +select '{"a":2,"b":3,"c":4}' @@ '%: ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":5}' @@ '%: ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":5}' @@ '% ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":"x"}' @@ '%: ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":4}' @@ '*: ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":5}' @@ '*: ($ > 1 and $ < 5)'::jsquery; +select '{"a":2,"b":3,"c":4}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; +select '{"a":2,"b":3,"c":5}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; +select '{"b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 1 and $ < 5))'::jsquery; +select '{"b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 0 and $ < 5))'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 0 and $ < 5))'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '* ($ > 0 and $ < 5)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR $ is numeric)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is numeric)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":8}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":"x"}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; +select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":null}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '%:.aa is numeric'::jsquery; +select '{"a":{"aa":1}, "b":{"aa":true, "bb":2}}' @@ '%:.aa is numeric'::jsquery; +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}, "aa":16}' @@ '*: (not $ is object or $.aa is numeric)'::jsquery; +select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '*: (not $ is object or $.aa is numeric or % is object)'::jsquery; +SELECT 'test.# IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)'::jsquery; + +select '[]' @@ '(@# > 0 and #: = 16)'::jsquery; +select '[16]' @@ '(@# > 0 and #: = 16)'::jsquery; + +--extract entries for index scan + +SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); +SELECT gin_debug_query_path_value('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); +SELECT gin_debug_query_path_value('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); +SELECT gin_debug_query_path_value('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); +SELECT gin_debug_query_path_value('#(x = "a" and y > 0 and y < 1 and z > 0)'); +SELECT gin_debug_query_path_value('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); +SELECT gin_debug_query_path_value('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); +SELECT gin_debug_query_path_value('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); +SELECT gin_debug_query_path_value('%.x = 1'); +SELECT gin_debug_query_path_value('*.x = "b"'); +SELECT gin_debug_query_path_value('x && [1,2,3]'); +SELECT gin_debug_query_path_value('x @> [1,2,3]'); +SELECT gin_debug_query_path_value('x <@ [1,2,3]'); +SELECT gin_debug_query_path_value('x = *'); +SELECT gin_debug_query_path_value('x is boolean'); +SELECT gin_debug_query_path_value('x is string'); +SELECT gin_debug_query_path_value('x is numeric'); +SELECT gin_debug_query_path_value('x is array'); +SELECT gin_debug_query_path_value('x is object'); +SELECT gin_debug_query_path_value('#:(x=1) AND %:(y=1) AND *:(z=1)'); +SELECT gin_debug_query_path_value('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); +SELECT gin_debug_query_path_value('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); + +SELECT gin_debug_query_value_path('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); +SELECT gin_debug_query_value_path('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); +SELECT gin_debug_query_value_path('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); +SELECT gin_debug_query_value_path('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); +SELECT gin_debug_query_value_path('#(x = "a" and y > 0 and y < 1 and z > 0)'); +SELECT gin_debug_query_value_path('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); +SELECT gin_debug_query_value_path('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); +SELECT gin_debug_query_value_path('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); +SELECT gin_debug_query_value_path('%.x = 1'); +SELECT gin_debug_query_value_path('*.x = "b"'); +SELECT gin_debug_query_value_path('x && [1,2,3]'); +SELECT gin_debug_query_value_path('x @> [1,2,3]'); +SELECT gin_debug_query_value_path('x <@ [1,2,3]'); +SELECT gin_debug_query_value_path('x = [1,2,3]'); +SELECT gin_debug_query_value_path('x = *'); +SELECT gin_debug_query_value_path('x is boolean'); +SELECT gin_debug_query_value_path('x is string'); +SELECT gin_debug_query_value_path('x is numeric'); +SELECT gin_debug_query_value_path('x is array'); +SELECT gin_debug_query_value_path('x is object'); +SELECT gin_debug_query_value_path('#:(x=1) AND %:(y=1) AND *:(z=1)'); +SELECT gin_debug_query_value_path('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); +SELECT gin_debug_query_value_path('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); +SELECT gin_debug_query_value_path('(@# > 0 and #: = 16)'); +SELECT gin_debug_query_value_path('*.@# ($ = 4 or $ = 2)'); + +---table and index + +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 19; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 < 19; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 >= 19; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 <= 19; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 = 19; +select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 16 AND + (v->>'review_helpful_votes')::int4 < 20; + + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; +select count(*) from test_jsquery where v @@ 'customer_id = null'; +select count(*) from test_jsquery where v @@ 'review_votes = true'; +select count(*) from test_jsquery where v @@ 'product_group = false'; +select count(*) from test_jsquery where v @@ 't = *'; +select count(*) from test_jsquery where v @@ 't is boolean'; +select count(*) from test_jsquery where v @@ 't is string'; +select count(*) from test_jsquery where v @@ 't is numeric'; +select count(*) from test_jsquery where v @@ 't is array'; +select count(*) from test_jsquery where v @@ 't is object'; +select count(*) from test_jsquery where v @@ '$ is boolean'; +select count(*) from test_jsquery where v @@ '$ is string'; +select count(*) from test_jsquery where v @@ '$ is numeric'; +select count(*) from test_jsquery where v @@ '$ is array'; +select count(*) from test_jsquery where v @@ '$ is object'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; +select count(*) from test_jsquery where v @@ '$ > 2'; +select count(*) from test_jsquery where v @@ '$ = false'; + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; +select v from test_jsquery where v @@ 'array && [2,3]' order by v; +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + +create index t_idx on test_jsquery using gin (v jsonb_value_path_ops); +set enable_seqscan = off; + +explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; +select count(*) from test_jsquery where v @@ 'customer_id = null'; +select count(*) from test_jsquery where v @@ 'review_votes = true'; +select count(*) from test_jsquery where v @@ 'product_group = false'; +select count(*) from test_jsquery where v @@ 't = *'; +select count(*) from test_jsquery where v @@ 't is boolean'; +select count(*) from test_jsquery where v @@ 't is string'; +select count(*) from test_jsquery where v @@ 't is numeric'; +select count(*) from test_jsquery where v @@ 't is array'; +select count(*) from test_jsquery where v @@ 't is object'; +select count(*) from test_jsquery where v @@ '$ is boolean'; +select count(*) from test_jsquery where v @@ '$ is string'; +select count(*) from test_jsquery where v @@ '$ is numeric'; +select count(*) from test_jsquery where v @@ '$ is array'; +select count(*) from test_jsquery where v @@ '$ is object'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; +select count(*) from test_jsquery where v @@ '$ > 2'; +select count(*) from test_jsquery where v @@ '$ = false'; + +explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; +select v from test_jsquery where v @@ 'array && [2,3]' order by v; +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + +drop index t_idx; + +create index t_idx on test_jsquery using gin (v jsonb_path_value_ops); +set enable_seqscan = off; + +explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; + +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND + v @@ 'review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; +select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; +select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; +select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; +select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; +select count(*) from test_jsquery where v @@ 'customer_id = null'; +select count(*) from test_jsquery where v @@ 'review_votes = true'; +select count(*) from test_jsquery where v @@ 'product_group = false'; +select count(*) from test_jsquery where v @@ 't = *'; +select count(*) from test_jsquery where v @@ 't is boolean'; +select count(*) from test_jsquery where v @@ 't is string'; +select count(*) from test_jsquery where v @@ 't is numeric'; +select count(*) from test_jsquery where v @@ 't is array'; +select count(*) from test_jsquery where v @@ 't is object'; +select count(*) from test_jsquery where v @@ '$ is boolean'; +select count(*) from test_jsquery where v @@ '$ is string'; +select count(*) from test_jsquery where v @@ '$ is numeric'; +select count(*) from test_jsquery where v @@ '$ is array'; +select count(*) from test_jsquery where v @@ '$ is object'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; +select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; +select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; +select count(*) from test_jsquery where v @@ '$ > 2'; +select count(*) from test_jsquery where v @@ '$ = false'; + +explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; +explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; + +select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; +select v from test_jsquery where v @@ 'array && [2,3]' order by v; +select v from test_jsquery where v @@ 'array @> [2,3]' order by v; +select v from test_jsquery where v @@ 'array = [2,3]' order by v; + +RESET enable_seqscan; diff --git a/jsquery/travis/dep-ubuntu-llvm.sh b/jsquery/travis/dep-ubuntu-llvm.sh new file mode 100644 index 0000000000..e640d5b5b2 --- /dev/null +++ b/jsquery/travis/dep-ubuntu-llvm.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cat ./travis/llvm-snapshot.gpg.key | sudo apt-key add - +echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-$(lsb_release -cs)-$LLVM_VER main" | sudo tee /etc/apt/sources.list.d/llvm.list diff --git a/jsquery/travis/dep-ubuntu-postgres.sh b/jsquery/travis/dep-ubuntu-postgres.sh new file mode 100644 index 0000000000..41c7d34643 --- /dev/null +++ b/jsquery/travis/dep-ubuntu-postgres.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cat ./travis/postgresql.gpg.key | sudo apt-key add - +echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PG_VER" | sudo tee /etc/apt/sources.list.d/pgdg.list diff --git a/jsquery/travis/llvm-snapshot.gpg.key b/jsquery/travis/llvm-snapshot.gpg.key new file mode 100644 index 0000000000..aa6b105aa3 --- /dev/null +++ b/jsquery/travis/llvm-snapshot.gpg.key @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQINBFE9lCwBEADi0WUAApM/mgHJRU8lVkkw0CHsZNpqaQDNaHefD6Rw3S4LxNmM +EZaOTkhP200XZM8lVdbfUW9xSjA3oPldc1HG26NjbqqCmWpdo2fb+r7VmU2dq3NM +R18ZlKixiLDE6OUfaXWKamZsXb6ITTYmgTO6orQWYrnW6ckYHSeaAkW0wkDAryl2 +B5v8aoFnQ1rFiVEMo4NGzw4UX+MelF7rxaaregmKVTPiqCOSPJ1McC1dHFN533FY +Wh/RVLKWo6npu+owtwYFQW+zyQhKzSIMvNujFRzhIxzxR9Gn87MoLAyfgKEzrbbT +DhqqNXTxS4UMUKCQaO93TzetX/EBrRpJj+vP640yio80h4Dr5pAd7+LnKwgpTDk1 +G88bBXJAcPZnTSKu9I2c6KY4iRNbvRz4i+ZdwwZtdW4nSdl2792L7Sl7Nc44uLL/ +ZqkKDXEBF6lsX5XpABwyK89S/SbHOytXv9o4puv+65Ac5/UShspQTMSKGZgvDauU +cs8kE1U9dPOqVNCYq9Nfwinkf6RxV1k1+gwtclxQuY7UpKXP0hNAXjAiA5KS5Crq +7aaJg9q2F4bub0mNU6n7UI6vXguF2n4SEtzPRk6RP+4TiT3bZUsmr+1ktogyOJCc +Ha8G5VdL+NBIYQthOcieYCBnTeIH7D3Sp6FYQTYtVbKFzmMK+36ERreL/wARAQAB +tD1TeWx2ZXN0cmUgTGVkcnUgLSBEZWJpYW4gTExWTSBwYWNrYWdlcyA8c3lsdmVz +dHJlQGRlYmlhbi5vcmc+iQI4BBMBAgAiBQJRPZQsAhsDBgsJCAcDAgYVCAIJCgsE +FgIDAQIeAQIXgAAKCRAVz00Yr090Ibx+EADArS/hvkDF8juWMXxh17CgR0WZlHCC +9CTBWkg5a0bNN/3bb97cPQt/vIKWjQtkQpav6/5JTVCSx2riL4FHYhH0iuo4iAPR +udC7Cvg8g7bSPrKO6tenQZNvQm+tUmBHgFiMBJi92AjZ/Qn1Shg7p9ITivFxpLyX +wpmnF1OKyI2Kof2rm4BFwfSWuf8Fvh7kDMRLHv+MlnK/7j/BNpKdozXxLcwoFBmn +l0WjpAH3OFF7Pvm1LJdf1DjWKH0Dc3sc6zxtmBR/KHHg6kK4BGQNnFKujcP7TVdv +gMYv84kun14pnwjZcqOtN3UJtcx22880DOQzinoMs3Q4w4o05oIF+sSgHViFpc3W +R0v+RllnH05vKZo+LDzc83DQVrdwliV12eHxrMQ8UYg88zCbF/cHHnlzZWAJgftg +hB08v1BKPgYRUzwJ6VdVqXYcZWEaUJmQAPuAALyZESw94hSo28FAn0/gzEc5uOYx +K+xG/lFwgAGYNb3uGM5m0P6LVTfdg6vDwwOeTNIExVk3KVFXeSQef2ZMkhwA7wya +KJptkb62wBHFE+o9TUdtMCY6qONxMMdwioRE5BYNwAsS1PnRD2+jtlI0DzvKHt7B +MWd8hnoUKhMeZ9TNmo+8CpsAtXZcBho0zPGz/R8NlJhAWpdAZ1CmcPo83EW86Yq7 +BxQUKnNHcwj2ebkCDQRRPZQsARAA4jxYmbTHwmMjqSizlMJYNuGOpIidEdx9zQ5g +zOr431/VfWq4S+VhMDhs15j9lyml0y4ok215VRFwrAREDg6UPMr7ajLmBQGau0Fc +bvZJ90l4NjXp5p0NEE/qOb9UEHT7EGkEhaZ1ekkWFTWCgsy7rRXfZLxB6sk7pzLC +DshyW3zjIakWAnpQ5j5obiDy708pReAuGB94NSyb1HoW/xGsGgvvCw4r0w3xPStw +F1PhmScE6NTBIfLliea3pl8vhKPlCh54Hk7I8QGjo1ETlRP4Qll1ZxHJ8u25f/ta +RES2Aw8Hi7j0EVcZ6MT9JWTI83yUcnUlZPZS2HyeWcUj+8nUC8W4N8An+aNps9l/ +21inIl2TbGo3Yn1JQLnA1YCoGwC34g8QZTJhElEQBN0X29ayWW6OdFx8MDvllbBV +ymmKq2lK1U55mQTfDli7S3vfGz9Gp/oQwZ8bQpOeUkc5hbZszYwP4RX+68xDPfn+ +M9udl+qW9wu+LyePbW6HX90LmkhNkkY2ZzUPRPDHZANU5btaPXc2H7edX4y4maQa +xenqD0lGh9LGz/mps4HEZtCI5CY8o0uCMF3lT0XfXhuLksr7Pxv57yue8LLTItOJ +d9Hmzp9G97SRYYeqU+8lyNXtU2PdrLLq7QHkzrsloG78lCpQcalHGACJzrlUWVP/ +fN3Ht3kAEQEAAYkCHwQYAQIACQUCUT2ULAIbDAAKCRAVz00Yr090IbhWEADbr50X +OEXMIMGRLe+YMjeMX9NG4jxs0jZaWHc/WrGR+CCSUb9r6aPXeLo+45949uEfdSsB +pbaEdNWxF5Vr1CSjuO5siIlgDjmT655voXo67xVpEN4HhMrxugDJfCa6z97P0+ML +PdDxim57uNqkam9XIq9hKQaurxMAECDPmlEXI4QT3eu5qw5/knMzDMZj4Vi6hovL +wvvAeLHO/jsyfIdNmhBGU2RWCEZ9uo/MeerPHtRPfg74g+9PPfP6nyHD2Wes6yGd +oVQwtPNAQD6Cj7EaA2xdZYLJ7/jW6yiPu98FFWP74FN2dlyEA2uVziLsfBrgpS4l +tVOlrO2YzkkqUGrybzbLpj6eeHx+Cd7wcjI8CalsqtL6cG8cUEjtWQUHyTbQWAgG +5VPEgIAVhJ6RTZ26i/G+4J8neKyRs4vz+57UGwY6zI4AB1ZcWGEE3Bf+CDEDgmnP +LSwbnHefK9IljT9XU98PelSryUO/5UPw7leE0akXKB4DtekToO226px1VnGp3Bov +1GBGvpHvL2WizEwdk+nfk8LtrLzej+9FtIcq3uIrYnsac47Pf7p0otcFeTJTjSq3 +krCaoG4Hx0zGQG2ZFpHrSrZTVy6lxvIdfi0beMgY6h78p6M9eYZHQHc02DjFkQXN +bXb5c6gCHESH5PXwPU4jQEE7Ib9J6sbk7ZT2Mw== +=j+4q +-----END PGP PUBLIC KEY BLOCK----- diff --git a/jsquery/travis/pg-travis-test.sh b/jsquery/travis/pg-travis-test.sh new file mode 100644 index 0000000000..1c192aba95 --- /dev/null +++ b/jsquery/travis/pg-travis-test.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +set -eux + +sudo apt-get update + + +# required packages +apt_packages="postgresql-$PG_VER postgresql-server-dev-$PG_VER postgresql-common build-essential flex bison" + +# exit code +status=0 + +# pg_config path +pg_ctl_path=/usr/lib/postgresql/$PG_VER/bin/pg_ctl +initdb_path=/usr/lib/postgresql/$PG_VER/bin/initdb +config_path=/usr/lib/postgresql/$PG_VER/bin/pg_config + + +# bug: http://www.postgresql.org/message-id/20130508192711.GA9243@msgid.df7cb.de +sudo update-alternatives --remove-all postmaster.1.gz + +# stop all existing instances (because of https://github.com/travis-ci/travis-cookbooks/pull/221) +sudo service postgresql stop +# ... and make sure they don't come back +echo 'exit 0' | sudo tee /etc/init.d/postgresql +sudo chmod a+x /etc/init.d/postgresql + +# install required packages +sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y install -qq $apt_packages + + +# perform code analysis if necessary +if [ $CHECK_CODE = "true" ]; then + + if [ "$CC" = "clang" ]; then + sudo apt-get -y install -qq clang-$LLVM_VER + + scan-build-$LLVM_VER --status-bugs \ + -disable-checker deadcode.DeadStores \ + make USE_PGXS=1 USE_ASSERT_CHECKING=1 PG_CONFIG=$config_path || status=$? + exit $status + + elif [ "$CC" = "gcc" ]; then + sudo apt-get -y install -qq cppcheck + + cppcheck --template "{file} ({line}): {severity} ({id}): {message}" \ + --enable=warning,portability,performance \ + --suppress=redundantAssignment \ + --suppress=uselessAssignmentPtrArg \ + --suppress=incorrectStringBooleanError \ + --std=c89 *.c *.h 2> cppcheck.log + + if [ -s cppcheck.log ]; then + cat cppcheck.log + status=1 # error + fi + + exit $status + fi + + # don't forget to "make clean" + make clean USE_PGXS=1 PG_CONFIG=$config_path +fi + + +# create cluster 'test' +CLUSTER_PATH=$(pwd)/test_cluster +$initdb_path -D $CLUSTER_PATH -U $USER -A trust + +# build jsquery (using CFLAGS_SL for gcov) +make USE_PGXS=1 PG_CONFIG=$config_path CFLAGS_SL="$($config_path --cflags_sl) -coverage" +sudo make install USE_PGXS=1 PG_CONFIG=$config_path + +# check build +status=$? +if [ $status -ne 0 ]; then exit $status; fi + +# set permission to write postgres locks +sudo chown $USER /var/run/postgresql/ + +# start cluster 'test' +echo "port = 55435" >> $CLUSTER_PATH/postgresql.conf +$pg_ctl_path -D $CLUSTER_PATH start -l postgres.log -w + +# run regression tests +PGPORT=55435 PGUSER=$USER PG_CONFIG=$config_path make installcheck USE_PGXS=1 || status=$? + +# show diff if it exists +if test -f regression.diffs; then cat regression.diffs; fi + +#generate *.gcov files +gcov *.c *.h + +exit $status diff --git a/jsquery/travis/postgresql.gpg.key b/jsquery/travis/postgresql.gpg.key new file mode 100644 index 0000000000..8480576ece --- /dev/null +++ b/jsquery/travis/postgresql.gpg.key @@ -0,0 +1,77 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBE6XR8IBEACVdDKT2HEH1IyHzXkb4nIWAY7echjRxo7MTcj4vbXAyBKOfjja +UrBEJWHN6fjKJXOYWXHLIYg0hOGeW9qcSiaa1/rYIbOzjfGfhE4x0Y+NJHS1db0V +G6GUj3qXaeyqIJGS2z7m0Thy4Lgr/LpZlZ78Nf1fliSzBlMo1sV7PpP/7zUO+aA4 +bKa8Rio3weMXQOZgclzgeSdqtwKnyKTQdXY5MkH1QXyFIk1nTfWwyqpJjHlgtwMi +c2cxjqG5nnV9rIYlTTjYG6RBglq0SmzF/raBnF4Lwjxq4qRqvRllBXdFu5+2pMfC +IZ10HPRdqDCTN60DUix+BTzBUT30NzaLhZbOMT5RvQtvTVgWpeIn20i2NrPWNCUh +hj490dKDLpK/v+A5/i8zPvN4c6MkDHi1FZfaoz3863dylUBR3Ip26oM0hHXf4/2U +A/oA4pCl2W0hc4aNtozjKHkVjRx5Q8/hVYu+39csFWxo6YSB/KgIEw+0W8DiTII3 +RQj/OlD68ZDmGLyQPiJvaEtY9fDrcSpI0Esm0i4sjkNbuuh0Cvwwwqo5EF1zfkVj +Tqz2REYQGMJGc5LUbIpk5sMHo1HWV038TWxlDRwtOdzw08zQA6BeWe9FOokRPeR2 +AqhyaJJwOZJodKZ76S+LDwFkTLzEKnYPCzkoRwLrEdNt1M7wQBThnC5z6wARAQAB +tBxQb3N0Z3JlU1FMIERlYmlhbiBSZXBvc2l0b3J5iQJOBBMBCAA4AhsDBQsJCAcD +BRUKCQgLBRYCAwEAAh4BAheAFiEEuXsK/KoaR/BE8kSgf8x9RqzMTPgFAlhtCD8A +CgkQf8x9RqzMTPgECxAAk8uL+dwveTv6eH21tIHcltt8U3Ofajdo+D/ayO53LiYO +xi27kdHD0zvFMUWXLGxQtWyeqqDRvDagfWglHucIcaLxoxNwL8+e+9hVFIEskQAY +kVToBCKMXTQDLarz8/J030Pmcv3ihbwB+jhnykMuyyNmht4kq0CNgnlcMCdVz0d3 +z/09puryIHJrD+A8y3TD4RM74snQuwc9u5bsckvRtRJKbP3GX5JaFZAqUyZNRJRJ +Tn2OQRBhCpxhlZ2afkAPFIq2aVnEt/Ie6tmeRCzsW3lOxEH2K7MQSfSu/kRz7ELf +Cz3NJHj7rMzC+76Rhsas60t9CjmvMuGONEpctijDWONLCuch3Pdj6XpC+MVxpgBy +2VUdkunb48YhXNW0jgFGM/BFRj+dMQOUbY8PjJjsmVV0joDruWATQG/M4C7O8iU0 +B7o6yVv4m8LDEN9CiR6r7H17m4xZseT3f+0QpMe7iQjz6XxTUFRQxXqzmNnloA1T +7VjwPqIIzkj/u0V8nICG/ktLzp1OsCFatWXh7LbU+hwYl6gsFH/mFDqVxJ3+DKQi +vyf1NatzEwl62foVjGUSpvh3ymtmtUQ4JUkNDsXiRBWczaiGSuzD9Qi0ONdkAX3b +ewqmN4TfE+XIpCPxxHXwGq9Rv1IFjOdCX0iG436GHyTLC1tTUIKF5xV4Y0+cXIOI +RgQQEQgABgUCTpdI7gAKCRDFr3dKWFELWqaPAKD1TtT5c3sZz92Fj97KYmqbNQZP ++ACfSC6+hfvlj4GxmUjp1aepoVTo3weJAhwEEAEIAAYFAk6XSQsACgkQTFprqxLS +p64F8Q//cCcutwrH50UoRFejg0EIZav6LUKejC6kpLeubbEtuaIH3r2zMblPGc4i ++eMQKo/PqyQrceRXeNNlqO6/exHozYi2meudxa6IudhwJIOn1MQykJbNMSC2sGUp +1W5M1N5EYgt4hy+qhlfnD66LR4G+9t5FscTJSy84SdiOuqgCOpQmPkVRm1HX5X1+ +dmnzMOCk5LHHQuiacV0qeGO7JcBCVEIDr+uhU1H2u5GPFNHm5u15n25tOxVivb94 +xg6NDjouECBH7cCVuW79YcExH/0X3/9G45rjdHlKPH1OIUJiiX47OTxdG3dAbB4Q +fnViRJhjehFscFvYWSqXo3pgWqUsEvv9qJac2ZEMSz9x2mj0ekWxuM6/hGWxJdB+ ++985rIelPmc7VRAXOjIxWknrXnPCZAMlPlDLu6+vZ5BhFX0Be3y38f7GNCxFkJzl +hWZ4Cj3WojMj+0DaC1eKTj3rJ7OJlt9S9xnO7OOPEUTGyzgNIDAyCiu8F4huLPaT +ape6RupxOMHZeoCVlqx3ouWctelB2oNXcxxiQ/8y+21aHfD4n/CiIFwDvIQjl7dg +mT3u5Lr6yxuosR3QJx1P6rP5ZrDTP9khT30t+HZCbvs5Pq+v/9m6XDmi+NlU7Zuh +Ehy97tL3uBDgoL4b/5BpFL5U9nruPlQzGq1P9jj40dxAaDAX/WKJAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlB5KywFCQPDFt8ACgkQf8x9RqzM +TPhuCQ//QAjRSAOCQ02qmUAikT+mTB6baOAakkYq6uHbEO7qPZkv4E/M+HPIJ4wd +nBNeSQjfvdNcZBA/x0hr5EMcBneKKPDj4hJ0panOIRQmNSTThQw9OU351gm3YQct +AMPRUu1fTJAL/AuZUQf9ESmhyVtWNlH/56HBfYjE4iVeaRkkNLJyX3vkWdJSMwC/ +LO3Lw/0M3R8itDsm74F8w4xOdSQ52nSRFRh7PunFtREl+QzQ3EA/WB4AIj3VohIG +kWDfPFCzV3cyZQiEnjAe9gG5pHsXHUWQsDFZ12t784JgkGyO5wT26pzTiuApWM3k +/9V+o3HJSgH5hn7wuTi3TelEFwP1fNzI5iUUtZdtxbFOfWMnZAypEhaLmXNkg4zD +kH44r0ss9fR0DAgUav1a25UnbOn4PgIEQy2fgHKHwRpCy20d6oCSlmgyWsR40EPP +YvtGq49A2aK6ibXmdvvFT+Ts8Z+q2SkFpoYFX20mR2nsF0fbt1lfH65P64dukxeR +GteWIeNakDD40bAAOH8+OaoTGVBJ2ACJfLVNM53PEoftavAwUYMrR910qvwYfd/4 +6rh46g1Frr9SFMKYE9uvIJIgDsQB3QBp71houU4H55M5GD8XURYs+bfiQpJG1p7e +B8e5jZx1SagNWc4XwL2FzQ9svrkbg1Y+359buUiP7T6QXX2zY++JAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlEqbZUFCQg2wEEACgkQf8x9RqzM +TPhFMQ//WxAfKMdpSIA9oIC/yPD/dJpY/+DyouOljpE6MucMy/ArBECjFTBwi/j9 +NYM4ynAk34IkhuNexc1i9/05f5RM6+riLCLgAOsADDbHD4miZzoSxiVr6GQ3YXMb +OGld9kV9Sy6mGNjcUov7iFcf5Hy5w3AjPfKuR9zXswyfzIU1YXObiiZT38l55pp/ +BSgvGVQsvbNjsff5CbEKXS7q3xW+WzN0QWF6YsfNVhFjRGj8hKtHvwKcA02wwjLe +LXVTm6915ZUKhZXUFc0vM4Pj4EgNswH8Ojw9AJaKWJIZmLyW+aP+wpu6YwVCicxB +Y59CzBO2pPJDfKFQzUtrErk9irXeuCCLesDyirxJhv8o0JAvmnMAKOLhNFUrSQ2m ++3EnF7zhfz70gHW+EG8X8mL/EN3/dUM09j6TVrjtw43RLxBzwMDeariFF9yC+5bL +tnGgxjsB9Ik6GV5v34/NEEGf1qBiAzFmDVFRZlrNDkq6gmpvGnA5hUWNr+y0i01L +jGyaLSWHYjgw2UEQOqcUtTFK9MNzbZze4mVaHMEz9/aMfX25R6qbiNqCChveIm8m +Yr5Ds2zdZx+G5bAKdzX7nx2IUAxFQJEE94VLSp3npAaTWv3sHr7dR8tSyUJ9poDw +gw4W9BIcnAM7zvFYbLF5FNggg/26njHCCN70sHt8zGxKQINMc6SJAj0EEwEIACcC +GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlLpFRkFCQ6EJy0ACgkQf8x9RqzM +TPjOZA//Zp0e25pcvle7cLc0YuFr9pBv2JIkLzPm83nkcwKmxaWayUIG4Sv6pH6h +m8+S/CHQij/yFCX+o3ngMw2J9HBUvafZ4bnbI0RGJ70GsAwraQ0VlkIfg7GUw3Tz +voGYO42rZTru9S0K/6nFP6D1HUu+U+AsJONLeb6oypQgInfXQExPZyliUnHdipei +4WR1YFW6sjSkZT/5C3J1wkAvPl5lvOVthI9Zs6bZlJLZwusKxU0UM4Btgu1Sf3nn +JcHmzisixwS9PMHE+AgPWIGSec/N27a0KmTTvImV6K6nEjXJey0K2+EYJuIBsYUN +orOGBwDFIhfRk9qGlpgt0KRyguV+AP5qvgry95IrYtrOuE7307SidEbSnvO5ezNe +mE7gT9Z1tM7IMPfmoKph4BfpNoH7aXiQh1Wo+ChdP92hZUtQrY2Nm13cmkxYjQ4Z +gMWfYMC+DA/GooSgZM5i6hYqyyfAuUD9kwRN6BqTbuAUAp+hCWYeN4D88sLYpFh3 +paDYNKJ+Gf7Yyi6gThcV956RUFDH3ys5Dk0vDL9NiWwdebWfRFbzoRM3dyGP889a +OyLzS3mh6nHzZrNGhW73kslSQek8tjKrB+56hXOnb4HaElTZGDvD5wmrrhN94kby +Gtz3cydIohvNO9d90+29h0eGEDYti7j7maHkBKUAwlcPvMg5m3Y= +=DA1T +-----END PGP PUBLIC KEY BLOCK----- From 0adf0b224af7d4193821e6d742cc96786d1dbbf7 Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 18 Jul 2022 13:55:53 +0300 Subject: [PATCH 12/14] Update docker and remove jsquery --- Dockerfile | 275 +-- docker-entrypoint.sh | 396 +++- jsquery/.travis.yml | 35 - jsquery/META.json | 53 - jsquery/Makefile | 45 - jsquery/README.md | 357 --- jsquery/data/test_jsquery.data | 1034 --------- jsquery/expected/jsquery.out | 2923 ------------------------- jsquery/jsonb_gin_ops.c | 1353 ------------ jsquery/jsquery--1.0.sql | 293 --- jsquery/jsquery.control | 6 - jsquery/jsquery.h | 249 --- jsquery/jsquery_constr.c | 260 --- jsquery/jsquery_extract.c | 1021 --------- jsquery/jsquery_gram.y | 364 --- jsquery/jsquery_io.c | 403 ---- jsquery/jsquery_op.c | 1009 --------- jsquery/jsquery_scan.l | 508 ----- jsquery/jsquery_support.c | 251 --- jsquery/sql/jsquery.sql | 548 ----- jsquery/travis/dep-ubuntu-llvm.sh | 4 - jsquery/travis/dep-ubuntu-postgres.sh | 4 - jsquery/travis/llvm-snapshot.gpg.key | 52 - jsquery/travis/pg-travis-test.sh | 95 - jsquery/travis/postgresql.gpg.key | 77 - 25 files changed, 437 insertions(+), 11178 deletions(-) delete mode 100644 jsquery/.travis.yml delete mode 100644 jsquery/META.json delete mode 100644 jsquery/Makefile delete mode 100644 jsquery/README.md delete mode 100644 jsquery/data/test_jsquery.data delete mode 100644 jsquery/expected/jsquery.out delete mode 100644 jsquery/jsonb_gin_ops.c delete mode 100644 jsquery/jsquery--1.0.sql delete mode 100644 jsquery/jsquery.control delete mode 100644 jsquery/jsquery.h delete mode 100644 jsquery/jsquery_constr.c delete mode 100644 jsquery/jsquery_extract.c delete mode 100644 jsquery/jsquery_gram.y delete mode 100644 jsquery/jsquery_io.c delete mode 100644 jsquery/jsquery_op.c delete mode 100644 jsquery/jsquery_scan.l delete mode 100644 jsquery/jsquery_support.c delete mode 100644 jsquery/sql/jsquery.sql delete mode 100644 jsquery/travis/dep-ubuntu-llvm.sh delete mode 100644 jsquery/travis/dep-ubuntu-postgres.sh delete mode 100644 jsquery/travis/llvm-snapshot.gpg.key delete mode 100644 jsquery/travis/pg-travis-test.sh delete mode 100644 jsquery/travis/postgresql.gpg.key diff --git a/Dockerfile b/Dockerfile index b2a1680fa2..15b22df595 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,72 +1,74 @@ -# vim:set ft=dockerfile: -FROM debian:buster-slim +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM debian:bullseye-slim RUN set -ex; \ - if ! command -v gpg > /dev/null; then \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - fi + if ! command -v gpg > /dev/null; then \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gnupg \ + dirmngr \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + fi # explicitly set user/group IDs RUN set -eux; \ - groupadd -r postgres --gid=999; \ + groupadd -r postgres --gid=999; \ # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 - useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ + useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ # also create the postgres user's home directory with appropriate permissions # see https://github.com/docker-library/postgres/issues/274 - mkdir -p /var/lib/postgresql; \ - chown -R postgres:postgres /var/lib/postgresql + mkdir -p /var/lib/postgresql; \ + chown -R postgres:postgres /var/lib/postgresql # grab gosu for easy step-down from root # https://github.com/tianon/gosu/releases -ENV GOSU_VERSION 1.12 +ENV GOSU_VERSION 1.14 RUN set -eux; \ - savedAptMark="$(apt-mark showmanual)"; \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates wget; \ - rm -rf /var/lib/apt/lists/*; \ - dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ - wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ - wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ - gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ - gpgconf --kill all; \ - rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ - apt-mark auto '.*' > /dev/null; \ - [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ - apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ - chmod +x /usr/local/bin/gosu; \ - gosu --version; \ - gosu nobody true + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates wget; \ + rm -rf /var/lib/apt/lists/*; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default RUN set -eux; \ - if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ + if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) - grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ - sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ - ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ - fi; \ - apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ - localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 + grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ + ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + fi; \ + apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 ENV LANG en_US.utf8 RUN set -eux; \ - apt-get update; \ - apt-get install -y --no-install-recommends \ -# install "nss_wrapper" in case we need to fake "/etc/passwd" and "/etc/group" (especially for OpenShift) -# https://github.com/docker-library/postgres/issues/359 -# https://cwrap.org/nss_wrapper.html - libnss-wrapper \ -# install "xz-utils" for .sql.xz docker-entrypoint-initdb.d files - xz-utils \ - ; \ - rm -rf /var/lib/apt/lists/* + apt-get update; \ + apt-get install -y --no-install-recommends \ + libnss-wrapper \ + xz-utils \ + zstd \ + ; \ + rm -rf /var/lib/apt/lists/* RUN mkdir /docker-entrypoint-initdb.d @@ -74,109 +76,110 @@ RUN set -ex; \ # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 # uid PostgreSQL Debian Repository - key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ - gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/postgres.gpg; \ - command -v gpgconf > /dev/null && gpgconf --kill all; \ - rm -rf "$GNUPGHOME"; \ - apt-key list + key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ + export GNUPGHOME="$(mktemp -d)"; \ + mkdir -p /usr/local/share/keyrings/; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ + gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ + command -v gpgconf > /dev/null && gpgconf --kill all; \ + rm -rf "$GNUPGHOME" + +ENV PG_MAJOR 14 +ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin -ENV PG_MAJOR 13 -ENV PG_VERSION 13.1-1.pgdg100+1 +ENV PG_VERSION 14.4-1.pgdg110+1 RUN set -ex; \ - \ + \ # see note below about "*.pyc" files - export PYTHONDONTWRITEBYTECODE=1; \ - \ - dpkgArch="$(dpkg --print-architecture)"; \ - case "$dpkgArch" in \ - amd64 | arm64 | i386 | ppc64el) \ + export PYTHONDONTWRITEBYTECODE=1; \ + \ + dpkgArch="$(dpkg --print-architecture)"; \ + aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main $PG_MAJOR"; \ + case "$dpkgArch" in \ + amd64 | arm64 | ppc64el) \ # arches officialy built by upstream - echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ - apt-get update; \ - ;; \ - *) \ + echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + apt-get update; \ + ;; \ + *) \ # we're on an architecture upstream doesn't officially build for # let's build binaries from their published source packages - echo "deb-src http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main $PG_MAJOR" > /etc/apt/sources.list.d/pgdg.list; \ - \ - case "$PG_MAJOR" in \ - 9.* | 10 ) ;; \ - *) \ -# https://github.com/docker-library/postgres/issues/484 (clang-6.0 required, only available in stretch-backports) -# TODO remove this once we hit buster+ - echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list.d/pgdg.list; \ - ;; \ - esac; \ - \ - tempDir="$(mktemp -d)"; \ - cd "$tempDir"; \ - \ - savedAptMark="$(apt-mark showmanual)"; \ - \ -# build .deb files from upstream's source packages (which are verified by apt-get) - apt-get update; \ - # we need DEBIAN_FRONTEND on postgresql-13 for slapd ("Please enter the password for the admin entry in your LDAP directory."); see https://bugs.debian.org/929417 - DEBIAN_FRONTEND=noninteractive \ - apt-get build-dep -y \ - postgresql-common pgdg-keyring \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - ; \ - DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \ - apt-get source --compile \ - postgresql-common pgdg-keyring \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - ; \ -# we don't remove APT lists here because they get re-downloaded and removed later - \ -# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies -# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) - apt-mark showmanual | xargs apt-mark auto > /dev/null; \ - apt-mark manual $savedAptMark; \ - \ + echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + \ + tempDir="$(mktemp -d)"; \ + cd "$tempDir"; \ + \ # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) - ls -lAFh; \ - dpkg-scanpackages . > Packages; \ - grep '^Package: ' Packages; \ - echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ + apt-get update; \ + apt-get install -y --no-install-recommends dpkg-dev; \ + echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ + _update_repo() { \ + dpkg-scanpackages . > Packages; \ # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) # ... # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) - apt-get -o Acquire::GzipIndexes=false update; \ - ;; \ - esac; \ - \ - apt-get install -y --no-install-recommends postgresql-common; \ - sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ - apt-get install -y --no-install-recommends \ - "postgresql-$PG_MAJOR=$PG_VERSION" \ - ; \ - \ - rm -rf /var/lib/apt/lists/*; \ - \ - if [ -n "$tempDir" ]; then \ + apt-get -o Acquire::GzipIndexes=false update; \ + }; \ + _update_repo; \ + \ +# build .deb files from upstream's source packages (which are verified by apt-get) + nproc="$(nproc)"; \ + export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ +# we have to build postgresql-common first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/99f44476e258cae6bf9e919219fa2c5414fa2876 +# (and it "Depends: pgdg-keyring") + apt-get build-dep -y postgresql-common pgdg-keyring; \ + apt-get source --compile postgresql-common pgdg-keyring; \ + _update_repo; \ + apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ + apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ + \ +# we don't remove APT lists here because they get re-downloaded and removed later + \ +# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies +# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + apt-mark showmanual | xargs apt-mark auto > /dev/null; \ + apt-mark manual $savedAptMark; \ + \ + ls -lAFh; \ + _update_repo; \ + grep '^Package: ' Packages; \ + cd /; \ + ;; \ + esac; \ + \ + apt-get install -y --no-install-recommends postgresql-common; \ + sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ + apt-get install -y --no-install-recommends \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ + \ + rm -rf /var/lib/apt/lists/*; \ + \ + if [ -n "$tempDir" ]; then \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) - apt-get purge -y --auto-remove; \ - rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ - fi; \ - \ + apt-get purge -y --auto-remove; \ + rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi; \ + \ # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) - find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' + + find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ + \ + postgres --version # make the sample config easier to munge (and "correct by default") RUN set -eux; \ - dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ - cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ - ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ - sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ - grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample + dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ + cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ + ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ + sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ + grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql -ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin ENV PGDATA /var/lib/postgresql/data # this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" @@ -184,15 +187,13 @@ VOLUME /var/lib/postgresql/data COPY jsquery/ /opt/jsquery/ -RUN apt-get update && apt-get install -y build-essential bison flex postgresql-server-dev-13 +RUN apt-get update && apt-get install -y build-essential bison flex postgresql-server-dev-14 RUN cd /opt/jsquery \ && make USE_PGXS=1 \ && make USE_PGXS=1 install COPY docker-entrypoint.sh /usr/local/bin/ -RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \ - && ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL @@ -226,4 +227,4 @@ STOPSIGNAL SIGINT # that even 90 seconds may not be long enough in many instances. EXPOSE 5432 -CMD ["postgres"] \ No newline at end of file +CMD ["postgres"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index c133583ab3..1896cd85c5 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -set -e +set -Eeo pipefail +# TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables) # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -23,122 +24,323 @@ file_env() { unset "$fileVar" } -if [ "${1:0:1}" = '-' ]; then - set -- postgres "$@" -fi +# check to see if this file is being run or sourced from another script +_is_sourced() { + # https://unix.stackexchange.com/a/215279 + [ "${#FUNCNAME[@]}" -ge 2 ] \ + && [ "${FUNCNAME[0]}" = '_is_sourced' ] \ + && [ "${FUNCNAME[1]}" = 'source' ] +} + +# used to create initial postgres directories and if run as root, ensure ownership to the "postgres" user +docker_create_db_directories() { + local user; user="$(id -u)" -# allow the container to be started with `--user` -if [ "$1" = 'postgres' ] && [ "$(id -u)" = '0' ]; then mkdir -p "$PGDATA" - chown -R postgres "$PGDATA" - chmod 700 "$PGDATA" + # ignore failure since there are cases where we can't chmod (and PostgreSQL might fail later anyhow - it's picky about permissions of this directory) + chmod 700 "$PGDATA" || : - mkdir -p /var/run/postgresql - chown -R postgres /var/run/postgresql - chmod 775 /var/run/postgresql + # ignore failure since it will be fine when using the image provided directory; see also https://github.com/docker-library/postgres/pull/289 + mkdir -p /var/run/postgresql || : + chmod 775 /var/run/postgresql || : - # Create the transaction log directory before initdb is run (below) so the directory is owned by the correct user - if [ "$POSTGRES_INITDB_XLOGDIR" ]; then - mkdir -p "$POSTGRES_INITDB_XLOGDIR" - chown -R postgres "$POSTGRES_INITDB_XLOGDIR" - chmod 700 "$POSTGRES_INITDB_XLOGDIR" + # Create the transaction log directory before initdb is run so the directory is owned by the correct user + if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then + mkdir -p "$POSTGRES_INITDB_WALDIR" + if [ "$user" = '0' ]; then + find "$POSTGRES_INITDB_WALDIR" \! -user postgres -exec chown postgres '{}' + + fi + chmod 700 "$POSTGRES_INITDB_WALDIR" fi - exec gosu postgres "$BASH_SOURCE" "$@" -fi + # allow the container to be started with `--user` + if [ "$user" = '0' ]; then + find "$PGDATA" \! -user postgres -exec chown postgres '{}' + + find /var/run/postgresql \! -user postgres -exec chown postgres '{}' + + fi +} -if [ "$1" = 'postgres' ]; then - mkdir -p "$PGDATA" - chown -R "$(id -u)" "$PGDATA" 2>/dev/null || : - chmod 700 "$PGDATA" 2>/dev/null || : +# initialize empty PGDATA directory with new database via 'initdb' +# arguments to `initdb` can be passed via POSTGRES_INITDB_ARGS or as arguments to this function +# `initdb` automatically creates the "postgres", "template0", and "template1" dbnames +# this is also where the database user is created, specified by `POSTGRES_USER` env +docker_init_database_dir() { + # "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary + # see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html + local uid; uid="$(id -u)" + if ! getent passwd "$uid" &> /dev/null; then + # see if we can find a suitable "libnss_wrapper.so" (https://salsa.debian.org/sssd-team/nss-wrapper/-/commit/b9925a653a54e24d09d9b498a2d913729f7abb15) + local wrapper + for wrapper in {/usr,}/lib{/*,}/libnss_wrapper.so; do + if [ -s "$wrapper" ]; then + NSS_WRAPPER_PASSWD="$(mktemp)" + NSS_WRAPPER_GROUP="$(mktemp)" + export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP + local gid; gid="$(id -g)" + echo "postgres:x:$uid:$gid:PostgreSQL:$PGDATA:/bin/false" > "$NSS_WRAPPER_PASSWD" + echo "postgres:x:$gid:" > "$NSS_WRAPPER_GROUP" + break + fi + done + fi - # look specifically for PG_VERSION, as it is expected in the DB dir - if [ ! -s "$PGDATA/PG_VERSION" ]; then - file_env 'POSTGRES_INITDB_ARGS' - if [ "$POSTGRES_INITDB_XLOGDIR" ]; then - export POSTGRES_INITDB_ARGS="$POSTGRES_INITDB_ARGS --xlogdir $POSTGRES_INITDB_XLOGDIR" - fi - eval "initdb --username=postgres $POSTGRES_INITDB_ARGS" - - # check password first so we can output the warning before postgres - # messes it up - file_env 'POSTGRES_PASSWORD' - if [ "$POSTGRES_PASSWORD" ]; then - pass="PASSWORD '$POSTGRES_PASSWORD'" - authMethod=md5 - else - # The - option suppresses leading tabs but *not* spaces. :) - cat >&2 <<-'EOWARN' - **************************************************** - WARNING: No password has been set for the database. - This will allow anyone with access to the - Postgres port to access your database. In - Docker's default configuration, this is - effectively any other container on the same - system. - Use "-e POSTGRES_PASSWORD=password" to set - it in "docker run". - **************************************************** - EOWARN - - pass= - authMethod=trust - fi + if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then + set -- --waldir "$POSTGRES_INITDB_WALDIR" "$@" + fi - { - echo - echo "host all all all $authMethod" - } >> "$PGDATA/pg_hba.conf" + eval 'initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"' - # internal start of server in order to allow set-up using psql-client - # does not listen on external TCP/IP and waits until start finishes - PGUSER="${PGUSER:-postgres}" \ - pg_ctl -D "$PGDATA" \ - -o "-c listen_addresses='localhost'" \ - -w start + # unset/cleanup "nss_wrapper" bits + if [[ "${LD_PRELOAD:-}" == */libnss_wrapper.so ]]; then + rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP" + unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP + fi +} - file_env 'POSTGRES_USER' 'postgres' - file_env 'POSTGRES_DB' "$POSTGRES_USER" +# print large warning if POSTGRES_PASSWORD is long +# error if both POSTGRES_PASSWORD is empty and POSTGRES_HOST_AUTH_METHOD is not 'trust' +# print large warning if POSTGRES_HOST_AUTH_METHOD is set to 'trust' +# assumes database is not set up, ie: [ -z "$DATABASE_ALREADY_EXISTS" ] +docker_verify_minimum_env() { + # check password first so we can output the warning before postgres + # messes it up + if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then + cat >&2 <<-'EOWARN' - psql=( psql -v ON_ERROR_STOP=1 ) + WARNING: The supplied POSTGRES_PASSWORD is 100+ characters. - if [ "$POSTGRES_DB" != 'postgres' ]; then - "${psql[@]}" --username postgres <<-EOSQL - CREATE DATABASE "$POSTGRES_DB" ; - EOSQL - echo - fi + This will not work if used via PGPASSWORD with "psql". - if [ "$POSTGRES_USER" = 'postgres' ]; then - op='ALTER' - else - op='CREATE' - fi - "${psql[@]}" --username postgres <<-EOSQL - $op USER "$POSTGRES_USER" WITH SUPERUSER $pass ; - EOSQL - echo + https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412) + https://github.com/docker-library/postgres/issues/507 + + EOWARN + fi + if [ -z "$POSTGRES_PASSWORD" ] && [ 'trust' != "$POSTGRES_HOST_AUTH_METHOD" ]; then + # The - option suppresses leading tabs but *not* spaces. :) + cat >&2 <<-'EOE' + Error: Database is uninitialized and superuser password is not specified. + You must specify POSTGRES_PASSWORD to a non-empty value for the + superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run". + + You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all + connections without a password. This is *not* recommended. - psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" ) + See PostgreSQL documentation about "trust": + https://www.postgresql.org/docs/current/auth-trust.html + EOE + exit 1 + fi + if [ 'trust' = "$POSTGRES_HOST_AUTH_METHOD" ]; then + cat >&2 <<-'EOWARN' + ******************************************************************************** + WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow + anyone with access to the Postgres port to access your database without + a password, even if POSTGRES_PASSWORD is set. See PostgreSQL + documentation about "trust": + https://www.postgresql.org/docs/current/auth-trust.html + In Docker's default configuration, this is effectively any other + container on the same system. + + It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace + it with "-e POSTGRES_PASSWORD=password" instead to set a password in + "docker run". + ******************************************************************************** + EOWARN + fi +} +# usage: docker_process_init_files [file [file [...]]] +# ie: docker_process_init_files /always-initdb.d/* +# process initializer files, based on file extensions and permissions +docker_process_init_files() { + # psql here for backwards compatibility "${psql[@]}" + psql=( docker_process_sql ) + + echo + local f + for f; do + case "$f" in + *.sh) + # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936 + # https://github.com/docker-library/postgres/pull/452 + if [ -x "$f" ]; then + echo "$0: running $f" + "$f" + else + echo "$0: sourcing $f" + . "$f" + fi + ;; + *.sql) echo "$0: running $f"; docker_process_sql -f "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;; + *.sql.xz) echo "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;; + *.sql.zst) echo "$0: running $f"; zstd -dc "$f" | docker_process_sql; echo ;; + *) echo "$0: ignoring $f" ;; + esac echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done + done +} + +# Execute sql script, passed via stdin (or -f flag of pqsl) +# usage: docker_process_sql [psql-cli-args] +# ie: docker_process_sql --dbname=mydb <<<'INSERT ...' +# ie: docker_process_sql -f my-file.sql +# ie: docker_process_sql > "$PGDATA/pg_hba.conf" +} + +# start socket-only postgresql server for setting up or running scripts +# all arguments will be passed along as arguments to `postgres` (via pg_ctl) +docker_temp_server_start() { + if [ "$1" = 'postgres' ]; then + shift fi -fi -exec "$@" \ No newline at end of file + # internal start of server in order to allow setup using psql client + # does not listen on external TCP/IP and waits until start finishes + set -- "$@" -c listen_addresses='' -p "${PGPORT:-5432}" + + PGUSER="${PGUSER:-$POSTGRES_USER}" \ + pg_ctl -D "$PGDATA" \ + -o "$(printf '%q ' "$@")" \ + -w start +} + +# stop postgresql server after done setting up user and running scripts +docker_temp_server_stop() { + PGUSER="${PGUSER:-postgres}" \ + pg_ctl -D "$PGDATA" -m fast -w stop +} + +# check arguments for an option that would cause postgres to stop +# return true if there is one +_pg_want_help() { + local arg + for arg; do + case "$arg" in + # postgres --help | grep 'then exit' + # leaving out -C on purpose since it always fails and is unhelpful: + # postgres: could not access the server configuration file "/var/lib/postgresql/data/postgresql.conf": No such file or directory + -'?'|--help|--describe-config|-V|--version) + return 0 + ;; + esac + done + return 1 +} + +_main() { + # if first arg looks like a flag, assume we want to run postgres server + if [ "${1:0:1}" = '-' ]; then + set -- postgres "$@" + fi + + if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then + docker_setup_env + # setup data directories and permissions (when run as root) + docker_create_db_directories + if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" + fi + + # only run initialization on an empty data directory + if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD + + echo + echo 'PostgreSQL init process complete; ready for start up.' + echo + else + echo + echo 'PostgreSQL Database directory appears to contain a database; Skipping initialization' + echo + fi + fi + + exec "$@" +} + +if ! _is_sourced; then + _main "$@" +fi diff --git a/jsquery/.travis.yml b/jsquery/.travis.yml deleted file mode 100644 index 2f24ce5a96..0000000000 --- a/jsquery/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -os: - - linux - -sudo: required -dist: trusty - -language: c - -compiler: - - clang - - gcc - -before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -y install -qq wget ca-certificates; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source ./travis/dep-ubuntu-postgres.sh; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source ./travis/dep-ubuntu-llvm.sh; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi - -env: - global: - - LLVM_VER=4.0 - matrix: - - PG_VER=10 CHECK_CODE=true - - PG_VER=10 CHECK_CODE=false - - PG_VER=9.6 CHECK_CODE=true - - PG_VER=9.6 CHECK_CODE=false - - PG_VER=9.5 CHECK_CODE=true - - PG_VER=9.5 CHECK_CODE=false - - PG_VER=9.4 CHECK_CODE=true - - PG_VER=9.4 CHECK_CODE=false - -script: bash ./travis/pg-travis-test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/jsquery/META.json b/jsquery/META.json deleted file mode 100644 index 694210c9de..0000000000 --- a/jsquery/META.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "JsQuery", - "abstract": "JSON Query Language with GIN indexing support", - "description": "JsQuery provides additional functionality for JSONB, such as a simple and effective way to search in nested objects and arrays, and more comparison operators with index support. It does this by implementing a specialized search syntax, the @@ operator, and the jsquery type for search strings.", - "version": "1.0.1", - "maintainer": [ - "Teodor Sigaev ", - "Alexander Korotkov ", - "Oleg Bartunov " - ], - "license": { - "PostgreSQL": "http://www.postgresql.org/about/licence" - }, - "prereqs": { - "runtime": { - "requires": { - "PostgreSQL": "9.4.0" - }, - "recommends": { - "PostgreSQL": "9.6.5" - } - } - }, - "provides": { - "jsquery": { - "file": "sql/jsquery.sql", - "docfile": "README.md", - "version": "1.0.1", - "abstract": "JSON query language with GIN indexing support" - } - }, - "resources": { - "homepage": "https://github.com/postgrespro/jsquery", - "bugtracker": { - "web": "https://github.com/postgrespro/jsquery/issues" - }, - "repository": { - "url": "https://github.com/postgrespro/jsquery.git", - "web": "https://github.com/postgrespro/jsquery", - "type": "git" - } - }, - "generated_by": "Josh Berkus", - "meta-spec": { - "version": "1.0.0", - "url": "http://pgxn.org/meta/spec.txt" - }, - "tags": [ - "JSON", - "index", - "search" - ] -} \ No newline at end of file diff --git a/jsquery/Makefile b/jsquery/Makefile deleted file mode 100644 index d7d415c8a3..0000000000 --- a/jsquery/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# contrib/jsquery/Makefile - -MODULE_big = jsquery -OBJS = jsonb_gin_ops.o jsquery_constr.o jsquery_extract.o \ - jsquery_gram.o jsquery_io.o jsquery_op.o jsquery_support.o - -EXTENSION = jsquery -DATA = jsquery--1.0.sql -INCLUDES = jsquery.h - -REGRESS = jsquery -# We need a UTF8 database -ENCODING = UTF8 - -EXTRA_CLEAN = y.tab.c y.tab.h \ - jsquery_gram.c jsquery_scan.c jsquery_gram.h - -ifdef USE_PGXS -PG_CONFIG ?= pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) -else -subdir = contrib/jsquery -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global -include $(top_srcdir)/contrib/contrib-global.mk -endif - -ifdef USE_ASSERT_CHECKING -override CFLAGS += -DUSE_ASSERT_CHECKING -endif - -jsquery_gram.o: jsquery_scan.c - -jsquery_gram.c: BISONFLAGS += -d - -distprep: jsquery_gram.c jsquery_scan.c - -maintainer-clean: - rm -f jsquery_gram.c jsquery_scan.c jsquery_gram.h - -install: installincludes - -installincludes: - $(INSTALL_DATA) $(addprefix $(srcdir)/, $(INCLUDES)) '$(DESTDIR)$(includedir_server)/' diff --git a/jsquery/README.md b/jsquery/README.md deleted file mode 100644 index 3ce8dc83ac..0000000000 --- a/jsquery/README.md +++ /dev/null @@ -1,357 +0,0 @@ -[![Build Status](https://travis-ci.org/postgrespro/jsquery.svg?branch=master)](https://travis-ci.org/postgrespro/jsquery) -[![codecov](https://codecov.io/gh/postgrespro/jsquery/branch/master/graph/badge.svg)](https://codecov.io/gh/postgrespro/jsquery) - -JsQuery – json query language with GIN indexing support -======================================================= - -Introduction ------------- - -JsQuery – is a language to query jsonb data type, introduced in PostgreSQL -release 9.4. - -It's primary goal is to provide an additional functionality to jsonb -(currently missing in PostgreSQL), such as a simple and effective way -to search in nested objects and arrays, more comparison operators with -indexes support. We hope, that jsquery will be eventually a part of -PostgreSQL. - -Jsquery is released as jsquery data type (similar to tsquery) and @@ -match operator for jsonb. - -Authors -------- - - * Teodor Sigaev , Postgres Professional, Moscow, Russia - * Alexander Korotkov , Postgres Professional, Moscow, Russia - * Oleg Bartunov , Postgres Professional, Moscow, Russia - -Availability ------------- - -JsQuery is realized as an extension and not available in default PostgreSQL -installation. It is available from -[github](https://github.com/postgrespro/jsquery) -under the same license as -[PostgreSQL](https://www.postgresql.org/about/licence/) -and supports PostgreSQL 9.4+. - -Regards -------- - -Development was sponsored by [Wargaming.net](http://wargaming.net). - -Installation ------------- - -JsQuery is PostgreSQL extension which requires PostgreSQL 9.4 or higher. -Before build and install you should ensure following: - - * PostgreSQL version is 9.4 or higher. - * You have development package of PostgreSQL installed or you built - PostgreSQL from source. - * You have flex and bison installed on your system. JsQuery was tested on - flex 2.5.37-2.5.39, bison 2.7.12. - * Your PATH variable is configured so that pg\_config command available, or set PG_CONFIG variable. - -Typical installation procedure may look like this: - - $ git clone https://github.com/postgrespro/jsquery.git - $ cd jsquery - $ make USE_PGXS=1 - $ sudo make USE_PGXS=1 install - $ make USE_PGXS=1 installcheck - $ psql DB -c "CREATE EXTENSION jsquery;" - -JSON query language -------------------- - -JsQuery extension contains `jsquery` datatype which represents whole JSON query -as a single value (like `tsquery` does for fulltext search). The query is an -expression on JSON-document values. - -Simple expression is specified as `path binary_operator value` or -`path unary_operator`. See following examples. - - * `x = "abc"` – value of key "x" is equal to "abc"; - * `$ @> [4, 5, "zzz"]` – the JSON document is an array containing values - 4, 5 and "zzz"; - * `"abc xyz" >= 10` – value of key "abc xyz" is greater than or equal to 10; - * `volume IS NUMERIC` – type of key "volume" is numeric. - * `$ = true` – the whole JSON document is just a true. - * `similar_ids.@# > 5` – similar\_ids is an array or object of length greater - than 5; - * `similar_product_ids.# = "0684824396"` – array "similar\_product\_ids" - contains string "0684824396". - * `*.color = "red"` – there is object somewhere which key "color" has value - "red". - * `foo = *` – key "foo" exists in object. - -Path selects set of JSON values to be checked using given operators. In -the simplest case path is just an key name. In general path is key names and -placeholders combined by dot signs. Path can use following placeholders: - - * `#` – any index of array; - * `#N` – N-th index of array; - * `%` – any key of object; - * `*` – any sequence of array indexes and object keys; - * `@#` – length of array or object, could be only used as last component of - path; - * `$` – the whole JSON document as single value, could be only the whole path. - -Expression is true when operator is true against at least one value selected -by path. - -Key names could be given either with or without double quotes. Key names -without double quotes shouldn't contain spaces, start with number or concur -with jsquery keyword. - -The supported binary operators are: - - * Equality operator: `=`; - * Numeric comparison operators: `>`, `>=`, `<`, `<=`; - * Search in the list of scalar values using `IN` operator; - * Array comparison operators: `&&` (overlap), `@>` (contains), - `<@` (contained in). - -The supported unary operators are: - - * Check for existence operator: `= *`; - * Check for type operators: `IS ARRAY`, `IS NUMERIC`, `IS OBJECT`, `IS STRING` - and `IS BOOLEAN`. - -Expressions could be complex. Complex expression is a set of expressions -combined by logical operators (`AND`, `OR`, `NOT`) and grouped using braces. - -Examples of complex expressions are given below. - - * `a = 1 AND (b = 2 OR c = 3) AND NOT d = 1` - * `x.% = true OR x.# = true` - -Prefix expressions are expressions given in the form path (subexpression). -In this case path selects JSON values to be checked using given subexpression. -Check results are aggregated in the same way as in simple expressions. - - * `#(a = 1 AND b = 2)` – exists element of array which a key is 1 and b key is 2 - * `%($ >= 10 AND $ <= 20)` – exists object key which values is between 10 and 20 - -Path also could contain following special placeholders with "every" semantics: - - * `#:` – every indexes of array; - * `%:` – every key of object; - * `*:` – every sequence of array indexes and object keys. - -Consider following example. - - %.#:($ >= 0 AND $ <= 1) - -This example could be read as following: there is at least one key which value -is array of numerics between 0 and 1. - -We can rewrite this example in the following form with extra braces. - - %(#:($ >= 0 AND $ <= 1)) - -The first placeholder `%` checks that expression in braces is true for at least -one value in object. The second placeholder `#:` checks value to be array and -all its elements satisfy expressions in braces. - -We can rewrite this example without `#:` placeholder as follows. - - %(NOT #(NOT ($ >= 0 AND $ <= 1)) AND $ IS ARRAY) - -In this example we transform assertion that every element of array satisfy some -condition to assertion that there is no one element which doesn't satisfy the -same condition. - -Some examples of using paths are given below. - - * `numbers.#: IS NUMERIC` – every element of "numbers" array is numeric. - * `*:($ IS OBJECT OR $ IS BOOLEAN)` – JSON is a structure of nested objects - with booleans as leaf values. - * `#:.%:($ >= 0 AND $ <= 1)` – each element of array is object containing - only numeric values between 0 and 1. - * `documents.#:.% = *` – "documents" is array of objects containing at least - one key. - * `%.#: ($ IS STRING)` – JSON object contains at least one array of strings. - * `#.% = true` – at least one array element is objects which contains at least - one "true" value. - -Usage of path operators and braces need some explanation. When same path -operators are used multiple times they may refer different values while you can -refer same value multiple time by using braces and `$` operator. See following -examples. - - * `# < 10 AND # > 20` – exists element less than 10 and exists another element - greater than 20. - * `#($ < 10 AND $ > 20)` – exists element which both less than 10 and greater - than 20 (impossible). - * `#($ >= 10 AND $ <= 20)` – exists element between 10 and 20. - * `# >= 10 AND # <= 20` – exists element great or equal to 10 and exists - another element less or equal to 20. Query can be satisfied by array with - no elements between 10 and 20, for instance [0,30]. - -Same rules apply when you search inside objects and branchy structures. - -Type checking operators and "every" placeholders are useful for document -schema validation. JsQuery matchig operator `@@` is immutable and can be used -in CHECK constraint. See following example. - -```sql -CREATE TABLE js ( - id serial, - data jsonb, - CHECK (data @@ ' - name IS STRING AND - similar_ids.#: IS NUMERIC AND - points.#:(x IS NUMERIC AND y IS NUMERIC)'::jsquery)); -``` - -In this example check constraint validates that in "data" jsonb column: -value of "name" key is string, value of "similar_ids" key is array of numerics, -value of "points" key is array of objects which contain numeric values in -"x" and "y" keys. - -See our -[pgconf.eu presentation](http://www.sai.msu.su/~megera/postgres/talks/pgconfeu-2014-jsquery.pdf) -for more examples. - -GIN indexes ------------ - -JsQuery extension contains two operator classes (opclasses) for GIN which -provide different kinds of query optimization. - - * jsonb\_path\_value\_ops - * jsonb\_value\_path\_ops - -In each of two GIN opclasses jsonb documents are decomposed into entries. Each -entry is associated with particular value and it's path. Difference between -opclasses is in the entry representation, comparison and usage for search -optimization. - -For example, jsonb document -`{"a": [{"b": "xyz", "c": true}, 10], "d": {"e": [7, false]}}` -would be decomposed into following entries: - - * "a".#."b"."xyz" - * "a".#."c".true - * "a".#.10 - * "d"."e".#.7 - * "d"."e".#.false - -Since JsQuery doesn't support search in particular array index, we consider -all array elements to be equivalent. Thus, each array element is marked with -same `#` sign in the path. - -Major problem in the entries representation is its size. In the given example -key "a" is presented three times. In the large branchy documents with long -keys size of naive entries representation becomes unreasonable. Both opclasses -address this issue but in a slightly different way. - -### jsonb\_path\_value\_ops - -jsonb\_path\_value\_ops represents entry as pair of path hash and value. -Following pseudocode illustrates it. - - (hash(path_item_1.path_item_2. ... .path_item_n); value) - -In comparison of entries path hash is the higher part of entry and value is -its lower part. This determines the features of this opclass. Since path -is hashed and it is higher part of entry we need to know the full path to -the value in order to use it for search. However, once path is specified -we can use both exact and range searches very efficiently. - -### jsonb\_value\_path\_ops - -jsonb\_value\_path\_ops represents entry as pair of value and bloom filter -of path. - - (value; bloom(path_item_1) | bloom(path_item_2) | ... | bloom(path_item_n)) - -In comparison of entries value is the higher part of entry and bloom filter of -path is its lower part. This determines the features of this opclass. Since -value is the higher part of entry we can perform only exact value search -efficiently. Range value search is possible as well but we would have to -filter all the the different paths where matching values occur. Bloom filter -over path items allows index usage for conditions containing `%` and `*` in -their paths. - -### Query optimization - -JsQuery opclasses perform complex query optimization. Thus it's valuable for -developer or administrator to see the result of such optimization. -Unfortunately, opclasses aren't allowed to do any custom output to the -EXPLAIN. That's why JsQuery provides following functions which allows to see -how particular opclass optimizes given query. - - * gin\_debug\_query\_path\_value(jsquery) – for jsonb\_path\_value\_ops - * gin\_debug\_query\_value\_path(jsquery) – for jsonb\_value\_path\_ops - -Result of these functions is a textual representation of query tree which -leafs are GIN search entries. Following examples show different results of -query optimization by different opclasses. - - # SELECT gin_debug_query_path_value('x = 1 AND (*.y = 1 OR y = 2)'); - gin_debug_query_path_value - ---------------------------- - x = 1 , entry 0 + - - # SELECT gin_debug_query_value_path('x = 1 AND (*.y = 1 OR y = 2)'); - gin_debug_query_value_path - ---------------------------- - AND + - x = 1 , entry 0 + - OR + - *.y = 1 , entry 1 + - y = 2 , entry 2 + - -Unfortunately, jsonb have no statistics yet. That's why JsQuery optimizer has -to do imperative decision while selecting conditions to be evaluated using -index. This decision is made by assumtion that some condition types are less -selective than others. Optimizer divides conditions into following selectivity -class (listed by descending of selectivity). - - 1. Equality (x = c) - 2. Range (c1 < x < c2) - 3. Inequality (x > c) - 4. Is (x is type) - 5. Any (x = \*) - -Optimizer evades index evaluation of less selective conditions when possible. -For example, in the `x = 1 AND y > 0` query `x = 1` is assumed to be more -selective than `y > 0`. That's why index isn't used for evaluation of `y > 0`. - - # SELECT gin_debug_query_path_value('x = 1 AND y > 0'); - gin_debug_query_path_value - ---------------------------- - x = 1 , entry 0 + - -With lack of statistics decisions made by optimizer can be inaccurate. That's -why JsQuery supports hints. Comments `/*-- index */` and `/*-- noindex */` -placed in the conditions forces optimizer to use and not use index -correspondingly. - - SELECT gin_debug_query_path_value('x = 1 AND y /*-- index */ > 0'); - gin_debug_query_path_value - ---------------------------- - AND + - x = 1 , entry 0 + - y > 0 , entry 1 + - - SELECT gin_debug_query_path_value('x /*-- noindex */ = 1 AND y > 0'); - gin_debug_query_path_value - ---------------------------- - y > 0 , entry 0 + - -Contribution ------------- - -Please, notice, that JsQuery is still under development and while it's -stable and tested, it may contains some bugs. Don't hesitate to raise -[issues at github](https://github.com/postgrespro/jsquery/issues) with your -bug reports. - -If you're lacking of some functionality in JsQuery and feeling power to -implement it then you're welcome to make pull requests. - diff --git a/jsquery/data/test_jsquery.data b/jsquery/data/test_jsquery.data deleted file mode 100644 index 01d86607c2..0000000000 --- a/jsquery/data/test_jsquery.data +++ /dev/null @@ -1,1034 +0,0 @@ -{"product_id": "0739301985", "customer_id": "A38QYR68FTYMLF", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Skipping Christmas", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 350857, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440242002", "0385510438", "044023722X", "0440241537", "0440225701"], "review_helpful_votes": 0} -{"product_id": "1579902022", "customer_id": "A38RB1X3RP1KVS", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Ceramic Glaze Handbook", "review_rating": 2, "product_category": "Home & Garden", "product_sales_rank": 502565, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": ["0873418212", "0873418638", "0823005941", "0873493591", "0812217829"], "review_helpful_votes": 3} -{"product_id": "0140043128", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 34067, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "0140236015", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 180313, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "014028334X", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest (Penguin Great Books of the 20th Century)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 504816, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "0142000744", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1460803, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0451163966", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 758, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "0453008151", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest Cassette ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 657021, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "0670030589", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew Over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 363845, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "088103715X", "customer_id": "A38V7C5F8WBHFT", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "One Flew over the Cuckoo's Nest", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 491328, "product_subcategory": "General", "similar_product_ids": ["0316769487", "0684833395", "0440180295", "0393312836", "0140042598"], "review_helpful_votes": 0} -{"product_id": "097143400X", "customer_id": "A38YMVFX82QNNY", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Spades for Winners", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 560023, "product_subcategory": "Games", "similar_product_ids": ["0971434018", "1566251451", "0970631219", "1566251478", "0486236307"], "review_helpful_votes": 5} -{"product_id": "0060175281", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 274350, "product_subcategory": "Self-Help", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} -{"product_id": "0060928921", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 32519, "product_subcategory": "Self-Help", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} -{"product_id": "0061094943", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 7644, "product_subcategory": "New Age", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} -{"product_id": "069451778X", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 163327, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} -{"product_id": "0694525472", "customer_id": "A391C934UQL2S", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Manifest Your Destiny CD", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 41723, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["156170315X", "1401902154", "140190131X", "1561708755", "0061094757"], "review_helpful_votes": 2} -{"product_id": "1561719226", "customer_id": "A3928WDFMAH8T3", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Princess Diana", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 204716, "product_subcategory": "General", "similar_product_ids": ["0595243622", "1843170841", "1843170051", "1932270213", "0740747134"], "review_helpful_votes": 4} -{"product_id": "0671874756", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Mist ", "review_rating": 3, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 235472, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0671046179", "074352005X", "B00005BB4A", "074352585X", "0140869441"], "review_helpful_votes": 6} -{"product_id": "0451188462", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9607, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "0451188462", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9607, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "1568954204", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation (Wheeler Compass)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1087464, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "1568954204", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation (Wheeler Compass)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1087464, "product_subcategory": "General", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "1880418363", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 876086, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "1880418363", "customer_id": "A398W6EA3053J0", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Desperation", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 876086, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0451191013", "0451184963", "067102423X", "0451186362", "0345441036"], "review_helpful_votes": 0} -{"product_id": "B0000036R8", "customer_id": "A39A7PMGPZLU3C", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Slanted & Enchanted", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 47222, "product_subcategory": "General", "similar_product_ids": ["B00000JH3F", "B000002LRJ", "B000003TAL", "B00003WG0M", "B000003TBP"], "review_helpful_votes": 0} -{"product_id": "B000056PA6", "customer_id": "A39J6P6WZ3123O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Double Album", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 186939, "product_subcategory": "General", "similar_product_ids": ["B00006FWZR", "B0002062SW"], "review_helpful_votes": 0} -{"product_id": "0345350804", "customer_id": "A39LHZVO6GM1UN", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Best of H. P. Lovecraft", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 24893, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345384210", "0345329457", "034542204X", "0345384229", "034545829X"], "review_helpful_votes": 1} -{"product_id": "0399146113", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 1049, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} -{"product_id": "0425179613", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 84, "product_subcategory": "Biographies", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} -{"product_id": "0786229004", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 1011554, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} -{"product_id": "1565114485", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 278461, "product_subcategory": "Biographies & Memoirs", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} -{"product_id": "1565114493", "customer_id": "A39MY2G6HAAJAT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "It's Not About the Bike", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 18513, "product_subcategory": "General", "similar_product_ids": ["0385508719", "1579542700", "044842407X", "039915194X", "1579548911"], "review_helpful_votes": 0} -{"product_id": "B000059LIO", "customer_id": "A39YV82M0W26J5", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Chase of Gain", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 273222, "product_subcategory": "Alternative Rock", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "0141802820", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 990849, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} -{"product_id": "0141802847", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 686308, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} -{"product_id": "0451204948", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 28695, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} -{"product_id": "0670896764", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 237651, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} -{"product_id": "B00008RWPR", "customer_id": "A3A1GEZ7TAT124", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 118872, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 0} -{"product_id": "0671008749", "customer_id": "A3A47FWSCY5MF3", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "FEAR HALL THE BEGINNING", "review_rating": 1, "product_category": "Children's Books", "product_sales_rank": 315182, "product_subcategory": "Literature", "similar_product_ids": ["0671008757", "0671002937", "0671894277", "0671529560", "0671894285"], "review_helpful_votes": 0} -{"product_id": "0613191455", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 531619, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0671315285", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "7 Habits Of Highly Effective People Cd", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 4930, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0671663984", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "SEVEN HABITS OF HIGHLY EFFECTIVE PEOPLE ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 24029, "product_subcategory": "Self-Help", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0671687964", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 20933, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0671708635", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 405, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0762408332", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People, Miniature Edition", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 62430, "product_subcategory": "Business Life", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "1883219027", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 105050, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "188321923X", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 797624, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "1883219337", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 491926, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "B00005NBPJ", "customer_id": "A3SWZXMFQ6HH2Y", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Salinas Sessions", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 216727, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "188321937X", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 3961, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "1883219973", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 137836, "product_subcategory": "Business", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "1929494157", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 7 Habits of Highly Effective People", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 584125, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "9992006684", "customer_id": "A3A9YBXDWP63EV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Seven Habits of Highly Effective People/Cassettes", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 274919, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0684846659", "0671723650", "0743250974", "0671792806", "0684857162"], "review_helpful_votes": 1} -{"product_id": "0515132292", "customer_id": "A3AAWL56G1X1Y8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Wild", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 21008, "product_subcategory": "General", "similar_product_ids": ["082177512X", "0758203381", "0758200846", "0758200862", "0758203403"], "review_helpful_votes": 0} -{"product_id": "0061066206", "customer_id": "A3GE8S9SWTIBLF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Britney Spears", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 955464, "product_subcategory": "Arts & Literature", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B00005Y6YJ", "customer_id": "A3AD9XYOEDT5RG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Oz - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 1046, "product_subcategory": "General", "similar_product_ids": ["B00000FBH2", "B0000Y40PW", "B00031TYBC", "B0009GV9E6", "B0002ERXC2"], "review_helpful_votes": 2} -{"product_id": "B00005Y74V", "customer_id": "A3AD9XYOEDT5RG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Oz - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 18526, "product_subcategory": "General", "similar_product_ids": ["B00000FBH2", "B0000Y40PW", "B00031TYBC", "B0009GV9E6", "B0002ERXC2"], "review_helpful_votes": 2} -{"product_id": "0553487639", "customer_id": "A3AHF0928XXGDI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Rewind (Replica", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 607635, "product_subcategory": "Literature", "similar_product_ids": ["0553487655", "0553487663", "0553487671", "055348768X", "0553487477"], "review_helpful_votes": 1} -{"product_id": "1573226068", "customer_id": "A3AIXV6S91MXA5", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Drown", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 18817, "product_subcategory": "General", "similar_product_ids": ["0345381432", "0679781420", "0375705899", "0452268060", "0743212029"], "review_helpful_votes": 0} -{"product_id": "0684823454", "customer_id": "A3AKSXRPSMNBD7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "My Early Life", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 48686, "product_subcategory": "General", "similar_product_ids": ["0060925779", "0226106330", "1592249930", "1401300561", "0395599687"], "review_helpful_votes": 3} -{"product_id": "051513225X", "customer_id": "A3AO3E9HYX8EQK", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Pendragon", "review_rating": 3, "product_category": "Romance", "product_sales_rank": 75503, "product_subcategory": "General", "similar_product_ids": ["0515127213", "0515129933", "0515124206", "0515111317", "0515109746"], "review_helpful_votes": 19} -{"product_id": "0439112095", "customer_id": "A3APYWXL54R4R6", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Westward to Home", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 296984, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0439389003", "0439370582", "0439369088", "043936907X", "0140383190"], "review_helpful_votes": 6} -{"product_id": "B0000009S9", "customer_id": "A3ARS50BR4K4CF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Fillmore East - June 1971", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 13506, "product_subcategory": "Progressive", "similar_product_ids": ["B0000009SD", "B0000009SK", "B0000009S5", "B0000009S8", "B0000009SS"], "review_helpful_votes": 1} -{"product_id": "B00005RGKA", "customer_id": "A3AV5ERQ22MUEL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Five Iron Frenzy 2", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 21737, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV"], "review_helpful_votes": 0} -{"product_id": "B000002H33", "customer_id": "A3AVZYA1FP3V91", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Master of Puppets", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 1179, "product_subcategory": "General", "similar_product_ids": ["B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"], "review_helpful_votes": 0} -{"product_id": "B000002H34", "customer_id": "A3AVZYA1FP3V91", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Master of Puppets", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 206419, "product_subcategory": "General", "similar_product_ids": ["B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"], "review_helpful_votes": 0} -{"product_id": "0312077866", "customer_id": "A3AYHE64D8B2SP", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Radio Waves", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 529294, "product_subcategory": "Radio", "similar_product_ids": ["0879306645", "0812992652", "0814793827"], "review_helpful_votes": 1} -{"product_id": "0789475006", "customer_id": "A3AZAJ7W69IE9G", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Fairways", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 319971, "product_subcategory": "Golf", "similar_product_ids": ["0810949504", "0810941341", "0810933721", "0762722223", "1579651623"], "review_helpful_votes": 3} -{"product_id": "0934837163", "customer_id": "A3AZV6OXKSDKAD", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Silent Scream", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 24165, "product_subcategory": "Instructional", "similar_product_ids": ["1573411205", "0934837120", "B00028HBKM"], "review_helpful_votes": 7} -{"product_id": "0138947597", "customer_id": "A3B0DQ7XUNU5PU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Intranet Security", "review_rating": 1, "product_category": "Computers & Internet", "product_sales_rank": 723293, "product_subcategory": "Digital Business & Culture", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "B000002ADT", "customer_id": "A3BA8EGMN2G5W3", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Kind of Blue", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 117, "product_subcategory": "General", "similar_product_ids": ["B000002AGN", "B0000A118M", "B000000Y2F", "B00005614M", "B000005H7D"], "review_helpful_votes": 5} -{"product_id": "B00003XAQ5", "customer_id": "A3BA8EGMN2G5W3", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Kind Of Blue", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 14330, "product_subcategory": "General", "similar_product_ids": ["B000002AGN", "B0000A118M", "B000000Y2F", "B00005614M", "B000005H7D"], "review_helpful_votes": 5} -{"product_id": "0826210155", "customer_id": "A3BB7DN7TMPR8Q", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Ghost in the Little House", "review_rating": 1, "product_category": "Biographies & Memoirs", "product_sales_rank": 463834, "product_subcategory": "Arts & Literature", "similar_product_ids": ["0803279140", "0826211674", "0803279175", "0064406989", "0060278420"], "review_helpful_votes": 4} -{"product_id": "B00000I0PF", "customer_id": "A3BFJFJRXMWXAX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "When Pus Comes to Shove", "review_rating": 3, "product_category": "Rock", "product_sales_rank": 65105, "product_subcategory": "General", "similar_product_ids": ["B00004R8QG", "B00005T61I", "B0002VE1U2", "B00067HPCS", "B000068C7W"], "review_helpful_votes": 1} -{"product_id": "B00000JYPW", "customer_id": "A3BFJFJRXMWXAX", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Liberate Te Ex Inferis", "review_rating": 4, "product_category": "Christian & Gospel", "product_sales_rank": 21147, "product_subcategory": "Christian Rock", "similar_product_ids": ["B000006P3V", "B000059T5U", "B00008BNU5", "B0002IQ9SW", "B000069CKJ"], "review_helpful_votes": 0} -{"product_id": "B00004T99Z", "customer_id": "A3BJO1U7IZHDN7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Mer de Noms", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 1973, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0000AZJXQ", "B000641ZIQ", "B00005B36H", "B00000099Y", "B000000993"], "review_helpful_votes": 1} -{"product_id": "B00004T9RX", "customer_id": "A3BJO1U7IZHDN7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Mer de Noms", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 359411, "product_subcategory": "Alternative Styles", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "1561583774", "customer_id": "A3BO9UEYQ2NYWE", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Creating the Not So Big House", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 31279, "product_subcategory": "Home Design", "similar_product_ids": ["1561583766", "1561586137", "1561586188", "1561582298", "1561585335"], "review_helpful_votes": 15} -{"product_id": "1561586056", "customer_id": "A3BO9UEYQ2NYWE", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Creating the Not So Big House", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 24446, "product_subcategory": "Home Design", "similar_product_ids": ["1561583766", "1561586137", "1561586188", "1561582298", "1561585335"], "review_helpful_votes": 15} -{"product_id": "0843947462", "customer_id": "A3BPPDT8CEY5G7", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The House That Jack Built", "review_rating": 3, "product_category": "Horror", "product_sales_rank": 288279, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["084394935X", "0843946334", "0843952407", "0812522028", "0812545338"], "review_helpful_votes": 0} -{"product_id": "0375421041", "customer_id": "A3C5O0WY6LLENW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Dark Room ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 476024, "product_subcategory": "World Literature", "similar_product_ids": ["0156027402", "0385722109", "038572179X", "0140286233", "0375507256"], "review_helpful_votes": 7} -{"product_id": "0375726322", "customer_id": "A3C5O0WY6LLENW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Dark Room ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 389993, "product_subcategory": "General", "similar_product_ids": ["0156027402", "0140286233", "0385722109", "038572179X", "0375507256"], "review_helpful_votes": 7} -{"product_id": "B00005JKVZ", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 9181, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} -{"product_id": "B00005JKW0", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1321, "product_subcategory": "General", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} -{"product_id": "B000067JH8", "customer_id": "A3C7CCJF1Q0W4O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 56341, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 1} -{"product_id": "B00005QDVS", "customer_id": "A3C9I2XZ8HY0U6", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "This Way", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 7039, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00000F1CY", "B000002J2S", "B00008OWZE", "B00000K53Y", "B000089RVR"], "review_helpful_votes": 0} -{"product_id": "0425181685", "customer_id": "A3CHO24ZFMD1LD", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Narcissus in Chains (An Anita Blake, Vampire Hunter Novel, Book 10)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 134033, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0515136816", "0515134473", "0515134511", "0515134465", "0425198243"], "review_helpful_votes": 3} -{"product_id": "0515133876", "customer_id": "A3CHO24ZFMD1LD", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Narcissus in Chains (Anita Blake Vampire Hunter (Paperback))", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 7509, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0515136816", "0515134473", "0515134511", "0515134465", "0425198243"], "review_helpful_votes": 3} -{"product_id": "B00005YUNM", "customer_id": "A3CKF9RX4ADHG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "Sade - Lovers Live", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 9767, "product_subcategory": "General", "similar_product_ids": ["B000056MMD", "B000056MMC", "B00005Y3ZM", "B00005V9QJ", "B00008HCCF"], "review_helpful_votes": 4} -{"product_id": "B00005YUQS", "customer_id": "A3CKF9RX4ADHG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Video", "product_title": "Sade - Lovers Live", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 34586, "product_subcategory": "General", "similar_product_ids": ["B000056MMD", "B000056MMC", "B00005Y3ZM", "B00008HCCF", "B00005V9QJ"], "review_helpful_votes": 4} -{"product_id": "0312268017", "customer_id": "A3CU3GER3D7K7A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Accidental Pope", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 343027, "product_subcategory": "Christianity", "similar_product_ids": ["0812579224", "0812579216", "0812590554", "0385504535", "0425042588"], "review_helpful_votes": 2} -{"product_id": "0312282982", "customer_id": "A3CU3GER3D7K7A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Accidental Pope ", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 131115, "product_subcategory": "General", "similar_product_ids": ["0812579224", "0812579216", "0812590554", "0385504535", "1902881842"], "review_helpful_votes": 2} -{"product_id": "0385315279", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 7359, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} -{"product_id": "0553528610", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 406433, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} -{"product_id": "0553714473", "customer_id": "A3CWHQGC11T3OW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Fiery Cross", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 201281, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["044022425X", "0440217563", "0440215625", "0440212561", "0385337477"], "review_helpful_votes": 1} -{"product_id": "6303929478", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Muppet Sing Alongs - Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 21639, "product_subcategory": "Animation", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} -{"product_id": "6304089627", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4919, "product_subcategory": "Comedy", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} -{"product_id": "B00006472V", "customer_id": "A3D1SN7TFKK0KM", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Muppet Treasure Island", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 1203, "product_subcategory": "Characters & Series", "similar_product_ids": ["B000065V41", "B00000JYLT", "B00005BCJR", "B0000AM6HZ", "B00005JXY2"], "review_helpful_votes": 0} -{"product_id": "6300215555", "customer_id": "A3D33WFGYFW6DG", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "We're No Angels", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 162, "product_subcategory": "By Year", "similar_product_ids": ["630150528X", "079074886X", "B00003XAMY", "0790748789", "B00003XAMX"], "review_helpful_votes": 4} -{"product_id": "0062517821", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 97490, "product_subcategory": "Self-Help", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0062516965", "0743537246"], "review_helpful_votes": 17} -{"product_id": "006251783X", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 25513, "product_subcategory": "Self-Help", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0062516965", "0743537246"], "review_helpful_votes": 17} -{"product_id": "0694526606", "customer_id": "A3D9VXSUDX8J36", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "The Secret of the Shadow", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 444066, "product_subcategory": "Health, Mind & Body", "similar_product_ids": ["1573227358", "0060086270", "0060723947", "0743537246", "0062516965"], "review_helpful_votes": 17} -{"product_id": "B00005JKVZ", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 9181, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} -{"product_id": "B00005JKW0", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1321, "product_subcategory": "General", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} -{"product_id": "B000067JH8", "customer_id": "A3DBGIY74746UE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 56341, "product_subcategory": "Love & Romance", "similar_product_ids": ["B0000DG001", "B000683VI4", "B00000JGPC", "0446608955", "B0000CDRVU"], "review_helpful_votes": 3} -{"product_id": "6304935803", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton (Widescreen Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 30855, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} -{"product_id": "6304935811", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton", "review_rating": 5, "product_category": "Military & War", "product_sales_rank": 16952, "product_subcategory": "Action & Combat", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} -{"product_id": "6305622930", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Patton", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 23484, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} -{"product_id": "B00005PJ8O", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Patton", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 915, "product_subcategory": "General", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} -{"product_id": "B00005Q4GV", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Patton", "review_rating": 5, "product_category": "Military & War", "product_sales_rank": 291, "product_subcategory": "World War II", "similar_product_ids": ["B00005PJ8S", "B00005N5S3", "B000059HAI", "B00003CX97", "B00004RF9H"], "review_helpful_votes": 0} -{"product_id": "0195116313", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Making Sense of the Molly Maguires", "review_rating": 5, "product_category": "History", "product_sales_rank": 48270, "product_subcategory": "Americas", "similar_product_ids": ["B0001FGBLG", "0681828757", "0395979145", "1572493194", "0801828724"], "review_helpful_votes": 2} -{"product_id": "0312169922", "customer_id": "A3DGR4IGR73QGL", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Rune Cards", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 286086, "product_subcategory": "New Age", "similar_product_ids": ["0312097581", "0312135076", "0875425933", "0877285489", "1592230423"], "review_helpful_votes": 2} -{"product_id": "0345339703", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 42596, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0345339703", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 42596, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0395489318", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 162177, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0395489318", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 162177, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0553714775", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (BBC Full Cast Dramatization)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 986248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0553714775", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (BBC Full Cast Dramatization)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 986248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618002227", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 77882, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618002227", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 77882, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618129030", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 365264, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618129030", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 365264, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618153985", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 813447, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618153985", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 813447, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618260269", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 956259, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0618260269", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 956259, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "061826051X", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 218871, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "061826051X", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 218871, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0788789538", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106027, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0788789538", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106027, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0788789813", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 17171, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0788789813", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 17171, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0808520768", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (Lord of the Rings (Paperback))", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 862897, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "0808520768", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (Lord of the Rings (Paperback))", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 862897, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "1556903219", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 2256332, "product_subcategory": "Children's Books", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "1556903219", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Book 1)", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 2256332, "product_subcategory": "Children's Books", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "1565116674", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Books on CD", "product_sales_rank": 707553, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "1565116674", "customer_id": "A3DI1URLN4M9V9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Fellowship of the Ring (The Lord of the Rings, Part 1)", "review_rating": 4, "product_category": "Books on CD", "product_sales_rank": 707553, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["078878983X", "0788789848", "0395177111", "0345325818", "0590353403"], "review_helpful_votes": 0} -{"product_id": "B00000I1PT", "customer_id": "A3DIG2DP9536FN", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Gilad Step Aerobics - On the Beach at Waikiki", "review_rating": 5, "product_category": "Fitness", "product_sales_rank": 11000, "product_subcategory": "General", "similar_product_ids": ["6302967945", "6303182364", "1573309931", "6302872162", "1573309966"], "review_helpful_votes": 3} -{"product_id": "0316606103", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Cirque Du Freak #2", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 112022, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} -{"product_id": "0316606847", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Vampire's Assistant (Cirque du Freak, Book 2)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 81251, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} -{"product_id": "0786237341", "customer_id": "A3DKK9LQ3NNQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Cirque Du Freak", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1481041, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 3} -{"product_id": "B00005RKTS", "customer_id": "A3DMTE8US4ARIJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Interzone Mantras", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 16795, "product_subcategory": "Goth & Industrial", "similar_product_ids": ["B0002Q9WEM", "B00000JOQ3", "B000003JE3", "B000003JD0", "B00002ZZH9"], "review_helpful_votes": 1} -{"product_id": "B00005A8OB", "customer_id": "A3DQ0INH14A1N6", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Lars Frederiksen & The Bastards", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 7215, "product_subcategory": "General", "similar_product_ids": ["B00027JYV2", "B00004W52U", "B00006JTGU", "B000001IQH", "B000001IPP"], "review_helpful_votes": 0} -{"product_id": "B00004XQW4", "customer_id": "A3DQ0INH14A1N6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Let Me Go E.P.", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 209804, "product_subcategory": "General", "similar_product_ids": ["B00027JYV2", "B000001IR1", "B00004UEHL", "B000007OED", "B000001IPP"], "review_helpful_votes": 0} -{"product_id": "0028612744", "customer_id": "A3DQHHCPK03MO6", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Complete Idiot's Guide to Buying or Leasing a Car (The Complete Idiot's Guide)", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 752789, "product_subcategory": "General", "similar_product_ids": ["0028625242", "0141001496", "0764550918", "0890439850", "0877596905"], "review_helpful_votes": 3} -{"product_id": "0553712853", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 340794, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} -{"product_id": "060960922X", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 152704, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} -{"product_id": "1400046831", "customer_id": "A3DU2FLLIYUE8A", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Love Is the Killer App ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 6296, "product_subcategory": "Business Life", "similar_product_ids": ["1400080495", "0787967076", "0875848192", "0738204307", "0385512058"], "review_helpful_votes": 4} -{"product_id": "0780020405", "customer_id": "A3E2UT8NVCLMLH", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "The Night Porter", "review_rating": 3, "product_category": "Cult Movies", "product_sales_rank": 17568, "product_subcategory": "Drama", "similar_product_ids": ["B0000WN10O", "B00005JKGO", "B0000WN118", "B00005JMIJ", "B0000WN0ZK"], "review_helpful_votes": 4} -{"product_id": "0780022823", "customer_id": "A3E2UT8NVCLMLH", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "The Night Porter - Criterion Collection", "review_rating": 3, "product_category": "Art House & International", "product_sales_rank": 7920, "product_subcategory": "By Genre", "similar_product_ids": ["B0000WN10O", "B00005JKGO", "B00005JMIJ", "B0000WN118", "B00023P4I8"], "review_helpful_votes": 4} -{"product_id": "0967143934", "customer_id": "A3E9PWC2B1EHDB", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Marketing to American Latinos", "review_rating": 3, "product_category": "Business & Investing", "product_sales_rank": 573031, "product_subcategory": "General", "similar_product_ids": ["0595287298", "0765612917", "0520227247", "0534241921", "0972529055"], "review_helpful_votes": 1} -{"product_id": "0967143977", "customer_id": "A3E9PWC2B1EHDB", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Marketing to American Latinos", "review_rating": 3, "product_category": "Business & Investing", "product_sales_rank": 674865, "product_subcategory": "General", "similar_product_ids": ["0595287298", "0765612917", "0520227247", "0534241921", "0972529055"], "review_helpful_votes": 1} -{"product_id": "0609600575", "customer_id": "A3EDG6KTCARNUU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Dogs Never Lie About Love ", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 94346, "product_subcategory": "Animal Care & Pets", "similar_product_ids": ["0385314280", "0345448820", "034545281X", "0761518088", "0385317018"], "review_helpful_votes": 9} -{"product_id": "0609802011", "customer_id": "A3EDG6KTCARNUU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Dogs Never Lie About Love ", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 156867, "product_subcategory": "Animal Care & Pets", "similar_product_ids": ["0385314280", "0345448820", "034545281X", "0761518088", "0385317018"], "review_helpful_votes": 9} -{"product_id": "B00003CWQI", "customer_id": "A3EEGR2D3SJJ3N", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Fritz the Cat", "review_rating": 4, "product_category": "Animation", "product_sales_rank": 4055, "product_subcategory": "General", "similar_product_ids": ["B00005PJ6S", "0792846818", "B0001NBMIK", "0767836316", "6305641587"], "review_helpful_votes": 0} -{"product_id": "055358376X", "customer_id": "A3EF0QEZLMHT0R", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Maximum Ice", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 453656, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0553583794", "055358023X", "0553580264", "055357681X", "0812579844"], "review_helpful_votes": 3} -{"product_id": "B00005R09Z", "customer_id": "A3EJYJC25OJVKK", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Cure - Greatest Hits", "review_rating": 2, "product_category": "Alternative Rock", "product_sales_rank": 330, "product_subcategory": "General", "similar_product_ids": ["B000002MVM", "B00000DAGD", "B000002H70", "B000002MZ4", "B00000DG1R"], "review_helpful_votes": 1} -{"product_id": "B00005O0ST", "customer_id": "A3ETFYXFZ6WYX8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Anne of Green Gables - The Continuing Story", "review_rating": 1, "product_category": "Kids & Family", "product_sales_rank": 402, "product_subcategory": "General", "similar_product_ids": ["B00005YNTR", "0553609416", "B00019PDWK", "B00005NGVV", "B0000C2IUY"], "review_helpful_votes": 6} -{"product_id": "1892065037", "customer_id": "A3EU3AOJA5C33T", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "I Dare (Liaden Universe Novel Series)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 270579, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["1892065029", "0441010229", "0441009913", "0441009646", "0441009271"], "review_helpful_votes": 0} -{"product_id": "1892065126", "customer_id": "A3EU3AOJA5C33T", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "I Dare (Liaden Universe Novel Series)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1186248, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0441010229", "1892065029", "0441009913", "0441009646", "0441009271"], "review_helpful_votes": 0} -{"product_id": "6304744404", "customer_id": "A3EVZ97UPAZKY9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Event Horizon", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 26422, "product_subcategory": "General", "similar_product_ids": ["079073639X", "078062856X", "B00005JMZK", "0780622553", "B0002CHK1S"], "review_helpful_votes": 0} -{"product_id": "6305222916", "customer_id": "A3EVZ97UPAZKY9", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Event Horizon", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2456, "product_subcategory": "General", "similar_product_ids": ["079073639X", "078062856X", "B00005JMZK", "0780622553", "B0002CHK1S"], "review_helpful_votes": 0} -{"product_id": "1589894006", "customer_id": "A3F83O1T8Q719Z", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Legend of Rah and the Muggles", "review_rating": 1, "product_category": "", "product_sales_rank": 657028, "product_subcategory": "", "similar_product_ids": [], "review_helpful_votes": 5} -{"product_id": "0446601543", "customer_id": "A3F92NHH9VOJKB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Deadly Innocence", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 7012, "product_subcategory": "True Accounts", "similar_product_ids": ["055356854X", "0345465806", "2895940002", "0440204429", "0786015179"], "review_helpful_votes": 0} -{"product_id": "B00004WG90", "customer_id": "A3FAX9MR67HYOA", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "French & Saunders", "review_rating": 4, "product_category": "Television", "product_sales_rank": 35489, "product_subcategory": "General", "similar_product_ids": ["B00005U2KK", "B00005U2KL", "B0000A02YF", "B0006Z2KZW", "B0006Z2KZM"], "review_helpful_votes": 3} -{"product_id": "B00005UERL", "customer_id": "A3FAX9MR67HYOA", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "French & Saunders", "review_rating": 4, "product_category": "Comedy", "product_sales_rank": 23340, "product_subcategory": "General", "similar_product_ids": ["B00005U2KK", "B00005U2KL", "B0000A02YF", "B0006Z2KZW", "B0006Z2KZM"], "review_helpful_votes": 3} -{"product_id": "0743237188", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall On Your Knees (Oprah #45)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 5896, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} -{"product_id": "0743237196", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 519477, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} -{"product_id": "0743466527", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees (Oprah's Book Club)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 51277, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} -{"product_id": "1565116917", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees cass (Oprah's Book Club (St. Paul, Minn.).)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 170216, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} -{"product_id": "1565116925", "customer_id": "A3FDLV937TBSE3", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Fall on Your Knees", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 639401, "product_subcategory": "General", "similar_product_ids": ["0060586370", "0375703063", "0345439104", "0345443284", "0440226104"], "review_helpful_votes": 1} -{"product_id": "B00005899O", "customer_id": "A3FFKTKYGDG3HP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Tantric", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 5543, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0001977K6", "B000002RBX", "B00005O6K6", "B00000JWLU", "B0002A2VS2"], "review_helpful_votes": 0} -{"product_id": "B00005QZ7U", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Moulin Rouge (Double Digipack)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 1425, "product_subcategory": "General", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} -{"product_id": "B00005YTFG", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Moulin Rouge (Special Edition)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 4748, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} -{"product_id": "B000062XLM", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Moulin Rouge", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 48083, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} -{"product_id": "B000077VR3", "customer_id": "A3FKTDYMQ6R1J2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Moulin Rouge (Single Disc Edition)", "review_rating": 1, "product_category": "Musicals & Performing Arts", "product_sales_rank": 4836, "product_subcategory": "Musicals", "similar_product_ids": ["B00005JLSE", "B00005BJ2O", "B00005YW4Z", "B000060OFT", "B0001GOH6Q"], "review_helpful_votes": 2} -{"product_id": "0060608145", "customer_id": "A3FM0PAT23VTNA", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Jesus", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 28277, "product_subcategory": "Christianity", "similar_product_ids": ["0060609176", "0060526769", "0060610352", "0060609192", "0060608765"], "review_helpful_votes": 6} -{"product_id": "6305500908", "customer_id": "A3FMVF6W9D3TSB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Sonic the Hedgehog", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 10499, "product_subcategory": "Animation", "similar_product_ids": ["B0000AZT6G", "B00011ZBEI", "B0001MZ7BY", "B0001MZ7B4", "1879794047"], "review_helpful_votes": 0} -{"product_id": "B00000JGOK", "customer_id": "A3FMVF6W9D3TSB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Sonic The Hedgehog - The Movie", "review_rating": 4, "product_category": "Anime & Manga", "product_sales_rank": 35235, "product_subcategory": "By Studio", "similar_product_ids": ["B0000AZT6G", "B00011ZBEI", "B0001MZ7BY", "B0001MZ7B4", "1879794047"], "review_helpful_votes": 0} -{"product_id": "0375431489", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} -{"product_id": "0385503822", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} -{"product_id": "0440241073", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} -{"product_id": "0553528912", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} -{"product_id": "0553714635", "customer_id": "A3FQA87DX3NC7Y", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 1} -{"product_id": "B00005Y1NF", "customer_id": "A3FVO92GDDCYJW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "Star Trek The Next Generation - The Complete First Season", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 6137, "product_subcategory": "General", "similar_product_ids": ["B000062XFG", "B000063V8R", "B000063V8S", "B000063V8T", "B000063V8V"], "review_helpful_votes": 2} -{"product_id": "1893756084", "customer_id": "A3FZ3STI2X5RIM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "The Best", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 193689, "product_subcategory": "Investing", "similar_product_ids": ["0471710490", "0131446037", "0071437886", "140006337X", "0887309569"], "review_helpful_votes": 5} -{"product_id": "0967446805", "customer_id": "A3FZMHPQYQSE7D", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "123 A Family Counting Book", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 146113, "product_subcategory": "Baby-3", "similar_product_ids": ["0316738964", "188367266X", "1555835430", "1884834698", "1413416004"], "review_helpful_votes": 7} -{"product_id": "0446678546", "customer_id": "A3G31NPX7YU7TT", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "The Hell with Love ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 101327, "product_subcategory": "Poetry", "similar_product_ids": ["0446690287", "068480302X", "0786884274", "0767909089", "0609807927"], "review_helpful_votes": 8} -{"product_id": "B00005NZDW", "customer_id": "A3G3D68D9GTVFD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Songs from the West Coast", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 12899, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00061X95Q", "B000001EXB", "B0000089F2", "B000009EJU", "B000001EG4"], "review_helpful_votes": 3} -{"product_id": "B00000JMOI", "customer_id": "A3G3DXHBPXYDS4", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Video", "product_title": "Open Your Eyes", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 2039, "product_subcategory": "By Country", "similar_product_ids": ["B00005N8A9", "B00005JKMZ", "B00005JL57", "B00005JLQW", "1928639011"], "review_helpful_votes": 5} -{"product_id": "B00005LZOD", "customer_id": "A3G3DXHBPXYDS4", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "DVD", "product_title": "Open Your Eyes", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 5428, "product_subcategory": "By Genre", "similar_product_ids": ["B00005N8A9", "B00005JKMZ", "B00005JL57", "B00005JLQW", "1928639011"], "review_helpful_votes": 5} -{"product_id": "B0000062XK", "customer_id": "A3G81594MU0PM8", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Music", "product_title": "Odds & Sods", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 33229, "product_subcategory": "British Invasion", "similar_product_ids": ["B000002P2W", "B000002P2V", "B000002OX5", "B00000761Z", "B000002OX3"], "review_helpful_votes": 10} -{"product_id": "0205309151", "customer_id": "A3GB9OUJ1SI975", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Technology for Teaching", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 104804, "product_subcategory": "Education", "similar_product_ids": ["0761975659", "1557987912", "0534603092", "0807735868", "0130484032"], "review_helpful_votes": 1} -{"product_id": "B000001Y57", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Sailing the Seas of Cheese", "review_rating": 3, "product_category": "Alternative Rock", "product_sales_rank": 6082, "product_subcategory": "General", "similar_product_ids": ["B000001Y5P", "B0000645KT", "B000001Y73", "B000028TV7", "B000001Y47"], "review_helpful_votes": 0} -{"product_id": "B000028TV7", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Antipop", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 10197, "product_subcategory": "General", "similar_product_ids": ["B000001Y47", "B000001Y73", "B000001Y57", "B000001Y5P", "B0000645KT"], "review_helpful_votes": 0} -{"product_id": "0794807135", "customer_id": "A3GCWB2XQ85COJ", "review_date": {"$date": 1013644800000}, "review_votes": 49, "product_group": "Book", "product_title": "The Official U.S. Mint 50 State Quarters", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 15094, "product_subcategory": "Antiques & Collectibles", "similar_product_ids": ["1582380783", "0794807607", "158238097X", "0307090302", "1582380953"], "review_helpful_votes": 49} -{"product_id": "1573305715", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Sesame Street - The Alphabet Jungle Game", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 6512, "product_subcategory": "Educational", "similar_product_ids": ["0738920762", "B00005QFDV", "0738920770", "630227608X", "B000065U1L"], "review_helpful_votes": 0} -{"product_id": "B00005QFDW", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Sesame Street - The Alphabet Jungle Game", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 5774, "product_subcategory": "General", "similar_product_ids": ["0738920762", "B00005QFDV", "0738920770", "630227608X", "B000065U1L"], "review_helpful_votes": 0} -{"product_id": "6304279507", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Sesame Street - Telling the Truth", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 15880, "product_subcategory": "Educational", "similar_product_ids": ["6303911560", "B00009W0TY", "B00008QSAF", "0738920762", "B000065U1L"], "review_helpful_votes": 4} -{"product_id": "B00008QSAH", "customer_id": "A3GDPO66IQ4AVW", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Sesame Street - Telling the Truth", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 8291, "product_subcategory": "General", "similar_product_ids": ["6303911560", "B00009W0TY", "B00008QSAF", "0738920762", "B000065U1L"], "review_helpful_votes": 4} -{"product_id": "6301797973", "customer_id": "A3GDW190U77XN", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "High Anxiety", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 61, "product_subcategory": "General", "similar_product_ids": ["6305168857", "6301798643", "B00000K3CQ", "B0001Z4OXS", "6302946387"], "review_helpful_votes": 0} -{"product_id": "0061066206", "customer_id": "A3GE8S9SWTIBLF", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Britney Spears", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 955464, "product_subcategory": "Arts & Literature", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B00005Y1N2", "customer_id": "A3GG9Z4SIMU55E", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Gold", "review_rating": 2, "product_category": "Pop", "product_sales_rank": 9048, "product_subcategory": "General", "similar_product_ids": ["B000002JC4", "B00001QEOL", "B000088E4T", "B0000AM6LZ", "B00004YNGO"], "review_helpful_votes": 3} -{"product_id": "0765341921", "customer_id": "A3GK3C57LBH6WC", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Beyond Ender's Game", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 7715, "product_subcategory": "Science Fiction", "similar_product_ids": ["0765344955", "0765308738", "0312857586", "0812575717", "0765349981"], "review_helpful_votes": 2} -{"product_id": "1569246483", "customer_id": "A3GO7UV9XX14D8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Storyteller's Goddess", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 495907, "product_subcategory": "Social Sciences", "similar_product_ids": ["156924443X", "1569246173", "006250276X", "0062503545", "0892815507"], "review_helpful_votes": 2} -{"product_id": "0375431489", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} -{"product_id": "0385503822", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} -{"product_id": "0440241073", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} -{"product_id": "0553528912", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} -{"product_id": "0553714635", "customer_id": "A3GOW3GIFL270C", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Summons", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 0} -{"product_id": "0767002652", "customer_id": "A3GT2VY34AXBOJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Upstairs Downstairs - The Premiere Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 4869, "product_subcategory": "TV Series", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 7} -{"product_id": "B00005NKCM", "customer_id": "A3GT2VY34AXBOJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Upstairs Downstairs - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 5806, "product_subcategory": "A&E Home Video", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 7} -{"product_id": "0684819066", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 309670, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} -{"product_id": "0684853701", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A BEAUTIFUL MIND", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 37365, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} -{"product_id": "0743224574", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 11065, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} -{"product_id": "0743509889", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 850520, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0486296725", "0688168949"], "review_helpful_votes": 16} -{"product_id": "0743509897", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind ", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 296367, "product_subcategory": "Biographies & Memoirs", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} -{"product_id": "078624223X", "customer_id": "A3GVXCGOSI205U", "review_date": {"$date": 1013644800000}, "review_votes": 18, "product_group": "Book", "product_title": "A Beautiful Mind (Thorndike Press Large Print Biography Series)", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 987105, "product_subcategory": "General", "similar_product_ids": ["0691095272", "B00005JKQZ", "0786884061", "0688168949", "0486296725"], "review_helpful_votes": 16} -{"product_id": "0140443886", "customer_id": "A3GYHHYQEPEKJM", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Rome and Italy ", "review_rating": 5, "product_category": "History", "product_sales_rank": 50647, "product_subcategory": "Ancient", "similar_product_ids": ["0140443185", "014044145X", "0140448098", "0140443622", "0140440844"], "review_helpful_votes": 8} -{"product_id": "0780023382", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "The Confessions of Robert Crumb", "review_rating": 3, "product_category": "Documentary", "product_sales_rank": 49280, "product_subcategory": "General", "similar_product_ids": ["0767821505", "1840727160", "B00003CWQI", "0867193743", "0930193792"], "review_helpful_votes": 6} -{"product_id": "B00005UQ7P", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "The Confessions of Robert Crumb", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 26273, "product_subcategory": "Art & Artists", "similar_product_ids": ["0767821505", "1840727160", "B00003CWQI", "0867193743", "0930193792"], "review_helpful_votes": 6} -{"product_id": "078881172X", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 279, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} -{"product_id": "B00001QEE5", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Peter Pan (Limited Issue)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 2457, "product_subcategory": "Animation", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} -{"product_id": "B00005RDSM", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "Peter Pan (Special Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 2878, "product_subcategory": "Animation", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} -{"product_id": "B00005RDVW", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan (Special Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 4549, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} -{"product_id": "B00005RDWH", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Peter Pan", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 42438, "product_subcategory": "Adventure", "similar_product_ids": ["B00001QEE9", "B00001QEE7", "B00003CXCQ", "B00001QEE6", "B00001QEE8"], "review_helpful_votes": 4} -{"product_id": "0780023390", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Jackson Pollock - Love and Death on Long Island", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 26636, "product_subcategory": "Art & Artists", "similar_product_ids": ["B00005KHJJ", "B000055XMV", "B00005B6KO", "B000055XNK", "B00007ELEI"], "review_helpful_votes": 5} -{"product_id": "B00005UQ7S", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "Jackson Pollock - Love & Death on Long Island", "review_rating": 3, "product_category": "Special Interests", "product_sales_rank": 23399, "product_subcategory": "Art & Artists", "similar_product_ids": ["B00005KHJJ", "B000055XMV", "B00005B6KO", "B000055XNK", "B00007ELEI"], "review_helpful_votes": 5} -{"product_id": "B000059HE4", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Me & Isaac Newton", "review_rating": 4, "product_category": "Documentary", "product_sales_rank": 45693, "product_subcategory": "General", "similar_product_ids": ["B00006673N", "1565019822", "B00005B327", "B0000ZG0TA", "B0000B1OFS"], "review_helpful_votes": 6} -{"product_id": "B00005T30J", "customer_id": "A3H9JSM1SUTE4O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Me & Isaac Newton", "review_rating": 4, "product_category": "Documentary", "product_sales_rank": 32387, "product_subcategory": "General", "similar_product_ids": ["B00006673N", "1565019822", "B00005B327", "B0000ZG0TA", "B0000B1OFS"], "review_helpful_votes": 6} -{"product_id": "0471293520", "customer_id": "A3HE4NA272OIAH", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Management Consulting", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 516152, "product_subcategory": "General", "similar_product_ids": ["0070534489", "0970431708", "1581312563", "1581311672", "1578511917"], "review_helpful_votes": 5} -{"product_id": "0471444014", "customer_id": "A3HE4NA272OIAH", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Management Consulting", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 214355, "product_subcategory": "General", "similar_product_ids": ["0070534489", "0970431708", "1581312563", "1581311672", "1578511917"], "review_helpful_votes": 5} -{"product_id": "0684841215", "customer_id": "A3HEOREMM29XWV", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "SOMETHING HAPPENED", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 58644, "product_subcategory": "General", "similar_product_ids": ["0374522928", "0684841258", "0684804506", "0684839741", "0684833395"], "review_helpful_votes": 11} -{"product_id": "0781808073", "customer_id": "A3HFAR4RJ7Y0ME", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Afghan Food & Cookery", "review_rating": 5, "product_category": "Cooking, Food & Wine", "product_sales_rank": 17091, "product_subcategory": "General", "similar_product_ids": ["1403385904", "0781806690", "0936347775", "093421154X", "0781809711"], "review_helpful_votes": 6} -{"product_id": "0689815298", "customer_id": "A3HGWA477T9047", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Silverwing", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 786630, "product_subcategory": "Animals", "similar_product_ids": ["0689832877", "0689869886", "0060531800", "0060000023", "0060000074"], "review_helpful_votes": 2} -{"product_id": "0689825587", "customer_id": "A3HGWA477T9047", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "SILVERWING", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 34287, "product_subcategory": "Animals", "similar_product_ids": ["0689832877", "0689869886", "0060531800", "0060000023", "0060000074"], "review_helpful_votes": 2} -{"product_id": "B00005J78F", "customer_id": "A3HH1BDXTWK1LI", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Drums of Fu Manchu", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 37614, "product_subcategory": "Crime", "similar_product_ids": ["B0000JD28S", "B000051SH3", "B000051S39", "B000087F3E", "B000087F1H"], "review_helpful_votes": 6} -{"product_id": "B000087F3F", "customer_id": "A3HH1BDXTWK1LI", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Drums of Fu Manchu", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 21616, "product_subcategory": "Crime", "similar_product_ids": ["B0000JD28S", "B000051SH3", "B000051S39", "B000087F3E", "B000087F1H"], "review_helpful_votes": 6} -{"product_id": "0875886175", "customer_id": "A3HKSYKCEEDREW", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In Search of Teddy", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 829034, "product_subcategory": "Antiques & Collectibles", "similar_product_ids": [], "review_helpful_votes": 4} -{"product_id": "1560151234", "customer_id": "A3HMQJOCPLQVLM", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Spanish", "review_rating": 1, "product_category": "Reference", "product_sales_rank": 626333, "product_subcategory": "Foreign Languages", "similar_product_ids": ["1591252040", "159125423X", "159125227X", "1591500427", "0970682913"], "review_helpful_votes": 9} -{"product_id": "B00005M987", "customer_id": "A3HOEJL7PAR5KC", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "The Spirit Room", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 2295, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B00009LI14", "B0000646TK", "B000066NW0", "B0001UL7RY", "B0002ZYEKA"], "review_helpful_votes": 0} -{"product_id": "0394806220", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo! Can You? (Bright and Early Books for Beginning Beginners)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 32414, "product_subcategory": "Literature", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} -{"product_id": "0679882820", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo, Can You ", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 722, "product_subcategory": "Baby-3", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} -{"product_id": "0881034126", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mr. Brown Can Moo! Can You? (Bright & Early Book)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1402462, "product_subcategory": "Literature", "similar_product_ids": ["0679882812", "0679882839", "0679882804", "039480029X", "0394800133"], "review_helpful_votes": 2} -{"product_id": "6305772649", "customer_id": "A3HQHM7ISFLQ0X", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Classic Albums - Steely Dan", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 7228, "product_subcategory": "General", "similar_product_ids": ["6305846464", "B00004REQZ", "B0000AOV85", "6305320616", "B00005Q2Z4"], "review_helpful_votes": 0} -{"product_id": "B00005A46T", "customer_id": "A3HR0V43CV3WC1", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 1154, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B00000JCOV", "B0001NBMBC", "B00004WK3A", "B0000787EO", "B00007BHOE"], "review_helpful_votes": 0} -{"product_id": "B00005NNNG", "customer_id": "A3HR0V43CV3WC1", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 430847, "product_subcategory": "Alternative Metal", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0764554093", "customer_id": "A3HYF1XWSZ3GN8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Investment Clubs for Dummies", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 16457, "product_subcategory": "General", "similar_product_ids": ["1892547007", "0812930088", "0446671479", "0471392278", "0471369381"], "review_helpful_votes": 6} -{"product_id": "B0000039PW", "customer_id": "A3HYWS34OY5G3R", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Ready to Die", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 2798, "product_subcategory": "East Coast", "similar_product_ids": ["B0000039QA", "B00002S5DF", "B00005AQEQ", "B0000029GA", "B00000FCBH"], "review_helpful_votes": 0} -{"product_id": "B000000XEF", "customer_id": "A3I2VA6S94AB2G", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "The Fugs First Album", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 47285, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B000000XEG", "B00009WVSP", "B000066AUL", "B0000009RT", "B00000K0XX"], "review_helpful_votes": 7} -{"product_id": "0812516826", "customer_id": "A3I92PEEL1B62O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Catnap ", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 242579, "product_subcategory": "Mystery", "similar_product_ids": ["0812516834", "0812534417", "0812544145", "0812555066", "0812530365"], "review_helpful_votes": 2} -{"product_id": "B00005JKJA", "customer_id": "A3I9LMORUC5GAV", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Mulholland Drive", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 1320, "product_subcategory": "Thrillers", "similar_product_ids": ["B000063JDE", "B000060MWU", "B00005JMIJ", "B00005V3Z4", "B000056BP1"], "review_helpful_votes": 3} -{"product_id": "B000060MY6", "customer_id": "A3I9LMORUC5GAV", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Mulholland Dr.", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 14855, "product_subcategory": "Mystery", "similar_product_ids": ["B000063JDE", "B000060MWU", "B00005JMIJ", "B00005V3Z4", "B000056BP1"], "review_helpful_votes": 3} -{"product_id": "1579902022", "customer_id": "A3IAQRJT1T447V", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "The Ceramic Glaze Handbook", "review_rating": 3, "product_category": "Home & Garden", "product_sales_rank": 502565, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": ["0873418212", "0873418638", "0823005941", "0873493591", "0812217829"], "review_helpful_votes": 7} -{"product_id": "B00005V3WH", "customer_id": "A3ICVJEW6MCP3Z", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Essential Barbra Streisand", "review_rating": 5, "product_category": "Broadway & Vocalists", "product_sales_rank": 4282, "product_subcategory": "Classic Vocalists", "similar_product_ids": ["B00006LFGD", "B0000C1YZI", "B0000025EV", "B0000026W1", "B000002IVS"], "review_helpful_votes": 1} -{"product_id": "0790729709", "customer_id": "A3IK9BLS3BWM96", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Bodyguard (Full Screen Edition)", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 7581, "product_subcategory": "General", "similar_product_ids": ["B000059TEP", "6305696071", "B0002WZTOI", "B000065V3J", "B00005JN0W"], "review_helpful_votes": 1} -{"product_id": "6302779278", "customer_id": "A3IK9BLS3BWM96", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Bodyguard", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 4075, "product_subcategory": "General", "similar_product_ids": ["B000059TEP", "6305696071", "B0002WZTOI", "B000002VMD", "B000065V3J"], "review_helpful_votes": 1} -{"product_id": "B0000071B3", "customer_id": "A3IR0OQESNZO2M", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Eyewitness", "review_rating": 1, "product_category": "Rock", "product_sales_rank": 301460, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0783235798", "customer_id": "A3IYYU0P7CJJ14", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "The Love Letter", "review_rating": 3, "product_category": "Comedy", "product_sales_rank": 14220, "product_subcategory": "General", "similar_product_ids": ["0790739267", "B00006472R", "B0000CNY3G", "B0002S94C0", "B00004Z4ST"], "review_helpful_votes": 0} -{"product_id": "0783239416", "customer_id": "A3IYYU0P7CJJ14", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "The Love Letter", "review_rating": 3, "product_category": "Comedy", "product_sales_rank": 19866, "product_subcategory": "General", "similar_product_ids": ["0790739267", "B00006472R", "B0000CNY3G", "B0002S94C0", "B00004Z4ST"], "review_helpful_votes": 0} -{"product_id": "0521472423", "customer_id": "A3J5JTEB1OPT2Z", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Quantum Field Theory", "review_rating": 3, "product_category": "Science", "product_sales_rank": 1584147, "product_subcategory": "Physics", "similar_product_ids": ["0201503972", "0521831431", "0691010196", "0226870332", "0471941867"], "review_helpful_votes": 4} -{"product_id": "0521478146", "customer_id": "A3J5JTEB1OPT2Z", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Quantum Field Theory", "review_rating": 3, "product_category": "Science", "product_sales_rank": 127991, "product_subcategory": "Physics", "similar_product_ids": ["0201503972", "0521831431", "0691010196", "0226870332", "0471941867"], "review_helpful_votes": 4} -{"product_id": "0399148027", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 328310, "product_subcategory": "General", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} -{"product_id": "0425184943", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 182185, "product_subcategory": "General", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} -{"product_id": "158788254X", "customer_id": "A3J5VEWUZO5XH5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blue Diary", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 1070879, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0425179672", "0425174344", "0425184757", "042513699X", "0425168700"], "review_helpful_votes": 1} -{"product_id": "B00004Y2FT", "customer_id": "A3J7LWIOY7DHPZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Stars and Topsoil", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 14505, "product_subcategory": "British Alternative", "similar_product_ids": ["B00006L5PQ", "B00009ATJD", "B00004Y82V", "B00006L5PM", "B00001QEEV"], "review_helpful_votes": 0} -{"product_id": "0375431489", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons (Random House Large Print)", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 523150, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} -{"product_id": "0385503822", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 44074, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} -{"product_id": "0440241073", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 18015, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} -{"product_id": "0553528912", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 356505, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} -{"product_id": "0553714635", "customer_id": "A3JH84BS0FV0IZ", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Summons", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 301828, "product_subcategory": "Thrillers", "similar_product_ids": ["0440234743", "0440241537", "0440236673", "0440225701", "0440224764"], "review_helpful_votes": 3} -{"product_id": "0767902335", "customer_id": "A3JPYZGUWN0AFS", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Work as a Spiritual Practice ", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 86540, "product_subcategory": "Buddhism", "similar_product_ids": ["1569753008", "089281876X", "0385497911", "0517886200", "1570629838"], "review_helpful_votes": 11} -{"product_id": "B00005Y1U8", "customer_id": "A3JR7DSEOEK35H", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "After Everything Now This", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 89734, "product_subcategory": "General", "similar_product_ids": ["B00015HV74", "B00000AGLM", "B000006XLH", "B00006YXFX", "B000006XLF"], "review_helpful_votes": 1} -{"product_id": "B00005M1GK", "customer_id": "A3JZ4F6BY0PD1C", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Step It Up!", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 77518, "product_subcategory": "International", "similar_product_ids": ["B000000A0W", "B000000A1E", "B0000001HJ", "B0001XQ6FE", "B00015V59Y"], "review_helpful_votes": 1} -{"product_id": "0786866578", "customer_id": "A3K09ST87JCD6E", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dictionary of the Future", "review_rating": 5, "product_category": "Reference", "product_sales_rank": 98576, "product_subcategory": "Dictionaries & Thesauruses", "similar_product_ids": ["0399527494", "0312218990", "0887308570", "0887305946", "0786865237"], "review_helpful_votes": 2} -{"product_id": "0375406530", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 56756, "product_subcategory": "General", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} -{"product_id": "0375706410", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 3596, "product_subcategory": "General", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} -{"product_id": "1587880040", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 547875, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} -{"product_id": "1587883163", "customer_id": "A3K5I0NLLQZX0R", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Waiting", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 1880931, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0375422765", "0375714111", "1581950063", "0375724931", "0375702067"], "review_helpful_votes": 0} -{"product_id": "B00005RYCE", "customer_id": "A3KHPQTO7LFIVB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "I'm a Slave 4 U [Import CD]", "review_rating": 1, "product_category": "Pop", "product_sales_rank": 138936, "product_subcategory": "General", "similar_product_ids": ["B000069JAY", "B00005A7YT", "B000050X6R", "B0001B0VL6", "B000207NSU"], "review_helpful_votes": 3} -{"product_id": "B000051XY5", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The W", "review_rating": 4, "product_category": "Rap & Hip-Hop", "product_sales_rank": 37653, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00005U2LM", "B000002WPI", "B00001IVOR", "B000002HFU", "B000000OUJ"], "review_helpful_votes": 2} -{"product_id": "B000002WPH", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Enter The Wu-Tang (36 Chambers)", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 219871, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00001IVOR", "B000000OUJ", "B000002WU9", "B0000024JA", "B00005AQEQ"], "review_helpful_votes": 1} -{"product_id": "B000002WPI", "customer_id": "A3KJM20HD56Q25", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Enter the Wu-Tang (36 Chambers)", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 5528, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": ["B00001IVOR", "B000000OUJ", "B000002WU9", "B0000024JA", "B00005AQEQ"], "review_helpful_votes": 1} -{"product_id": "095253780X", "customer_id": "A3KN68AJ57XZBG", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Book", "product_title": "Around and About Paris, Volume 1", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 182164, "product_subcategory": "Europe", "similar_product_ids": ["0952537834", "0952537826", "1566564581", "0844201413", "0609804448"], "review_helpful_votes": 12} -{"product_id": "0385321414", "customer_id": "A3KTGMCRZJNWMA", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} -{"product_id": "0440418291", "customer_id": "A3KTGMCRZJNWMA", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} -{"product_id": "B000001EA8", "customer_id": "A3KXKMZ3U3PUD6", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Pre-Millennium Tension", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 9910, "product_subcategory": "General", "similar_product_ids": ["B000001E7V", "B000007P6K", "B000005HQN", "B00005LNH1", "B00000JWNY"], "review_helpful_votes": 6} -{"product_id": "0782140424", "customer_id": "A3KYVDMAPV5HM7", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Zoo Tycoon", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 120058, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["0782143571"], "review_helpful_votes": 9} -{"product_id": "6301801709", "customer_id": "A3L31489BCB1D7", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Wizards", "review_rating": 1, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 7670, "product_subcategory": "General", "similar_product_ids": ["0767836316", "B00003CWQI", "6305307156", "0792846818", "0767809548"], "review_helpful_votes": 4} -{"product_id": "B00005RYKU", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Glass House", "review_rating": 3, "product_category": "Mystery & Suspense", "product_sales_rank": 16524, "product_subcategory": "Suspense", "similar_product_ids": ["B00005UV34", "B000083C6I", "B00003CXI7", "B0001GF2D8", "B00005JMDZ"], "review_helpful_votes": 2} -{"product_id": "B00005RYP7", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Glass House", "review_rating": 3, "product_category": "Drama", "product_sales_rank": 10111, "product_subcategory": "General", "similar_product_ids": ["B00005UV34", "B000083C6I", "B0001GF2D8", "B00003CXI7", "B00005JKIV"], "review_helpful_votes": 2} -{"product_id": "0671774778", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Section 31", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 335748, "product_subcategory": "Science Fiction", "similar_product_ids": ["0671774786", "0671774719", "0671774832", "0743491718", "074346754X"], "review_helpful_votes": 2} -{"product_id": "0201696231", "customer_id": "A3L5XAPBLPO4FN", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "QuarkXPress 4 for Macintosh", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 195266, "product_subcategory": "Graphics & Illustration", "similar_product_ids": ["0764502425", "0201696959", "0201713098", "0844226289", "0201782634"], "review_helpful_votes": 1} -{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 0} -{"product_id": "B000002JWP", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 4908, "product_subcategory": "General", "similar_product_ids": ["B00005LMJU", "B000000518", "B00007B9W4", "B00000JQFH", "B000002GV6"], "review_helpful_votes": 3} -{"product_id": "B00005N588", "customer_id": "A3L5XLFAUF8SS8", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "One in a Million", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 74738, "product_subcategory": "General", "similar_product_ids": ["B000000518", "B00005LMJU", "B00007B9W4", "B00000ADG2", "B000002GV6"], "review_helpful_votes": 3} -{"product_id": "0842339523", "customer_id": "A3LGX5A0B5PQLX", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Book", "product_title": "Mark of the Lion ", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 3493, "product_subcategory": "Fiction", "similar_product_ids": ["1576738167", "0842335684", "0842319476", "084233498X", "084230052X"], "review_helpful_votes": 14} -{"product_id": "0963942972", "customer_id": "A3LQYVHNSEAKQX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Maui Revealed", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 229861, "product_subcategory": "United States", "similar_product_ids": ["0971727910", "0963942999", "0824826426", "0971727929", "0967007240"], "review_helpful_votes": 1} -{"product_id": "0971727902", "customer_id": "A3LQYVHNSEAKQX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Maui Revealed", "review_rating": 5, "product_category": "Travel", "product_sales_rank": 56739, "product_subcategory": "United States", "similar_product_ids": ["0971727910", "0963942999", "0824826426", "0971727929", "0967007240"], "review_helpful_votes": 1} -{"product_id": "6303027016", "customer_id": "A3LU79BYMWZEW9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Good Morning, Vietnam", "review_rating": 3, "product_category": "Military & War", "product_sales_rank": 103, "product_subcategory": "Comedy", "similar_product_ids": ["6305144168", "B00000IQV7", "6305216088", "B00005AUJQ", "B00003CXA2"], "review_helpful_votes": 1} -{"product_id": "6305144176", "customer_id": "A3LU79BYMWZEW9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Good Morning, Vietnam", "review_rating": 3, "product_category": "Military & War", "product_sales_rank": 4895, "product_subcategory": "Comedy", "similar_product_ids": ["6305144168", "B00000IQV7", "6305216088", "B00005AUJQ", "B00003CXA2"], "review_helpful_votes": 1} -{"product_id": "0553713582", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 250314, "product_subcategory": "Leaders & Notable People", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} -{"product_id": "0609609874", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 214974, "product_subcategory": "Current Events", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} -{"product_id": "140004684X", "customer_id": "A3M101NXM013H2", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "See No Evil", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 6857, "product_subcategory": "Politics", "similar_product_ids": ["1400050219", "067173458X", "1574888498", "0060957913", "1594200076"], "review_helpful_votes": 7} -{"product_id": "0786866209", "customer_id": "A3M174IC0VXOS2", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Conflict of Interest ", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 518610, "product_subcategory": "Thrillers", "similar_product_ids": ["0786889837", "0758206186", "0451180062", "0525935878", "0451180216"], "review_helpful_votes": 10} -{"product_id": "0451181425", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Manhattans and Murder (Murder She Wrote)", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 213956, "product_subcategory": "Mystery", "similar_product_ids": ["0451185129", "0451183835", "0451187717", "0451184912", "0451194756"], "review_helpful_votes": 1} -{"product_id": "0451183835", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Murder, She Wrote", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 347183, "product_subcategory": "Mystery", "similar_product_ids": ["0451184912", "0451181425", "0451185129", "0451187717", "0451188209"], "review_helpful_votes": 0} -{"product_id": "0451194756", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Murder, She Wrote ", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 174336, "product_subcategory": "Mystery", "similar_product_ids": ["0451192915", "0451185129", "0451201523", "0451187717", "0451208323"], "review_helpful_votes": 0} -{"product_id": "0451194764", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Murder at the Powderhorn Ranch (Murder She Wrote 11)", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 436066, "product_subcategory": "Mystery", "similar_product_ids": ["0451194772", "0451194748", "0451211715", "0451207211", "0451208323"], "review_helpful_votes": 2} -{"product_id": "0451188209", "customer_id": "A3M2DDUH552Z6H", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Palette for Murder (Murder She Wrote)", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 133051, "product_subcategory": "Mystery", "similar_product_ids": ["0451185129", "0451192915", "0451187717", "0451212843", "0451207211"], "review_helpful_votes": 2} -{"product_id": "0425169502", "customer_id": "A3MCQSIBV7QW8Q", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Darkest Knight (Star Wars", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 192945, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0425171531", "0425169057", "0425169499", "0425170616", "0425173135"], "review_helpful_votes": 3} -{"product_id": "0618127011", "customer_id": "A3MCW5KKOFAH3M", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "When Mountains Walked", "review_rating": 2, "product_category": "Literature & Fiction", "product_sales_rank": 111704, "product_subcategory": "General", "similar_product_ids": ["0861713540", "1573222674", "0375423079", "0395860326"], "review_helpful_votes": 2} -{"product_id": "0595204465", "customer_id": "A3MHPUCT09IHEX", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Five Points", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 527301, "product_subcategory": "Genre Fiction", "similar_product_ids": ["0452283612", "0374528993", "1560252758", "0805060049", "1560255218"], "review_helpful_votes": 10} -{"product_id": "B00005LB8B", "customer_id": "A3MOAWAHDRPPCI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "The Reduced Shakespeare Company - The Complete Works of William Shakespeare (Abridged)", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 11193, "product_subcategory": "General", "similar_product_ids": ["B00008NG9M", "B000777I88", "B0000DZTOM", "1557831572", "0881451487"], "review_helpful_votes": 3} -{"product_id": "B00008US5Q", "customer_id": "A3MOAWAHDRPPCI", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "The Reduced Shakespeare Company - The Complete Works of William Shakespeare (Abridged)", "review_rating": 5, "product_category": "", "product_sales_rank": 2773, "product_subcategory": "", "similar_product_ids": ["B000777I88", "B00008NG9M", "B0000DZTOM", "1557831572", "0881451487"], "review_helpful_votes": 3} -{"product_id": "0375409076", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Leadership by the Book", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 401699, "product_subcategory": "Business", "similar_product_ids": ["0849996597", "1562924885", "0688039693", "068815428X", "0688170366"], "review_helpful_votes": 1} -{"product_id": "0688172393", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Leadership by the Book ", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 153795, "product_subcategory": "Business Life", "similar_product_ids": ["0849996597", "1562924885", "0688039693", "068815428X", "0688170366"], "review_helpful_votes": 1} -{"product_id": "0785264051", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws Of Leadership, Workbook", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 22349, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} -{"product_id": "0785274316", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws of Leadership", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 444, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} -{"product_id": "0785274766", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The 21 Irrefutable Laws of Leadership", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 162830, "product_subcategory": "Christianity", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} -{"product_id": "0785294279", "customer_id": "A3MODDPEKD0GVQ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "21 Irrefutable Laws Of Leadership", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 914010, "product_subcategory": "Business", "similar_product_ids": ["0785274405", "0785266666", "0785274340", "0785264191", "0785263500"], "review_helpful_votes": 1} -{"product_id": "0486202410", "customer_id": "A3MOL7824BGDTR", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "An Atlas of Anatomy for Artists", "review_rating": 5, "product_category": "Arts & Photography", "product_sales_rank": 235641, "product_subcategory": "Graphic Design", "similar_product_ids": ["0486211045", "0486200825", "0195030958", "0823014010", "0486227081"], "review_helpful_votes": 2} -{"product_id": "B00003CY5J", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 9066, "product_subcategory": "Crime", "similar_product_ids": ["B00005UQ9T", "6305263248", "6305127697", "B0000B1OFL", "B00005LDDD"], "review_helpful_votes": 1} -{"product_id": "B000062XKK", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 83655, "product_subcategory": "Crime", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B000062XKL", "customer_id": "A3MSQL0L4DM98Q", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Score", "review_rating": 2, "product_category": "Mystery & Suspense", "product_sales_rank": 20775, "product_subcategory": "Crime", "similar_product_ids": ["B00005UQ9T", "6305263248", "6305127697", "B0000B1OFL", "B0006J28KU"], "review_helpful_votes": 1} -{"product_id": "B00005OW09", "customer_id": "A3MUY2NYW3XGZ5", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Trigun - The Complete Boxed Set", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 954, "product_subcategory": "General", "similar_product_ids": ["B00005QCW4", "B0001DCYCS", "B00008L3MH", "B0000639E0", "B00005NX1N"], "review_helpful_votes": 1} -{"product_id": "0691002703", "customer_id": "A3MWYPZBKL1NJ", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Orpheus and Power", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 435192, "product_subcategory": "Social Sciences", "similar_product_ids": ["1566395879", "080185251X", "0807854417", "0807844942", "0807849227"], "review_helpful_votes": 0} -{"product_id": "0446516570", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 182779, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} -{"product_id": "0446529931", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 501425, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} -{"product_id": "0446611913", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 24097, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} -{"product_id": "158621134X", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 120903, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} -{"product_id": "1586211366", "customer_id": "A3MYU99YQQ463L", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Up Country", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 421966, "product_subcategory": "Mystery", "similar_product_ids": ["0446301582", "0446608262", "0446353205", "0446605409", "0446358592"], "review_helpful_votes": 0} -{"product_id": "0944599273", "customer_id": "A3MZU97EKHUF4S", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Walt Disney's Uncle Scrooge & Donald Duck", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 58598, "product_subcategory": "Animals", "similar_product_ids": ["0944599281", "0944599249", "0944599001", "0944599028", "094459901X"], "review_helpful_votes": 7} -{"product_id": "B00000I2PG", "customer_id": "A3MZYSDR9DDSIH", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Lexicon Of Love", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 33997, "product_subcategory": "General", "similar_product_ids": ["B000001FD5", "B00005S84K", "B000005RYN", "B00005N8BG", "B00007MB2U"], "review_helpful_votes": 4} -{"product_id": "B0000057DL", "customer_id": "A3NCESLO69JCK4", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Monteverdi", "review_rating": 5, "product_category": "Classical", "product_sales_rank": 67577, "product_subcategory": "Featured Composers, A-Z", "similar_product_ids": ["B0000057CN", "B0000057CV", "B0000057F0", "B00000J9GR", "B00005K3P7"], "review_helpful_votes": 0} -{"product_id": "6301599330", "customer_id": "A3NIPOJ08YWIIL", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Faerie Tale Theatre - Little Red Riding Hood", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 12378, "product_subcategory": "General", "similar_product_ids": ["B00061UHZG", "B00061UHXI", "B00061UHYM", "B00061UHW4", "B00061UHVU"], "review_helpful_votes": 0} -{"product_id": "630575067X", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1599, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} -{"product_id": "630575070X", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 18465, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} -{"product_id": "6305750750", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition Boxed Set)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2872, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} -{"product_id": "B00003CX5P", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "DVD", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 28, "product_subcategory": "General", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B000634DCW"], "review_helpful_votes": 8} -{"product_id": "B0000667J7", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Video", "product_title": "Star Wars - Episode I, The Phantom Menace (Widescreen Edition Boxed Set)", "review_rating": 2, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 16432, "product_subcategory": "Series & Sequels", "similar_product_ids": ["B00003CXCT", "B0006Z2LMO", "B00005JN4W", "B00005JMAH", "B00005JMQW"], "review_helpful_votes": 8} -{"product_id": "B00003CXI0", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 280, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "B00003CXI1", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Special Widescreen Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 337, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "B000062TU1", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Full Screen Edition)", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 1576, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "B000062TU2", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone - Spanish Edition", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 4207, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "B00006IRHA", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 40700, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "B00006IRHB", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 3, "product_category": "Kids & Family", "product_sales_rank": 33519, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 1} -{"product_id": "0767802659", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Starship Troopers", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 8515, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B0001L3MI0", "B000244EMO"], "review_helpful_votes": 1} -{"product_id": "6304913176", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Starship Troopers", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 10313, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B000244EMO", "B0001L3MI0"], "review_helpful_votes": 1} -{"product_id": "B0000648WZ", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Starship Troopers (Special Edition)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 5059, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0006GVJE4", "B0001XAOQ6", "B00005JMZK", "B000244EMO", "B0001L3MI0"], "review_helpful_votes": 1} -{"product_id": "6304502095", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Video", "product_title": "Repulsion", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 20289, "product_subcategory": "General", "similar_product_ids": ["B000069I09", "B00005JKP9", "B00005JKGO", "B0006IUE9I", "B0002KQNKE"], "review_helpful_votes": 4} -{"product_id": "B00005KHJM", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Wicker Man", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 4596, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} -{"product_id": "B00005KHJR", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Wicker Man (Limited Edition)", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 10451, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} -{"product_id": "B00005KHKX", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Wicker Man", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 23676, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} -{"product_id": "B00005KHL5", "customer_id": "A3NM0RAYSL6PA8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Wicker Man (Unrated Edition)", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 9419, "product_subcategory": "Suspense", "similar_product_ids": ["B00006GOF7", "B000069I0A", "B00005R1N3", "B00005LQ04", "033039018X"], "review_helpful_votes": 2} -{"product_id": "0446528382", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 4541, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "0446529869", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 488065, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "0446690686", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 12228, "product_subcategory": "General", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "1586211722", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 485260, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "1586211730", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 275517, "product_subcategory": "Management & Leadership", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "1586211749", "customer_id": "A3NNYWJPSR564P", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Jack", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 393300, "product_subcategory": "Business", "similar_product_ids": ["0070581045", "0060753943", "0071409378", "0060523794", "0786868414"], "review_helpful_votes": 0} -{"product_id": "B00005V4Y7", "customer_id": "A3NOLKUXIEIKZJ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "Jackie's Back", "review_rating": 1, "product_category": "African American Cinema", "product_sales_rank": 22375, "product_subcategory": "Comedy", "similar_product_ids": ["B00008DDHJ", "B00007ELD8", "B0001NBMIU", "B0001DMUHM", "B00005LPZZ"], "review_helpful_votes": 0} -{"product_id": "B00005JJ1F", "customer_id": "A3NY5JFGYCD6JB", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Music", "product_title": "Copperhead", "review_rating": 2, "product_category": "Country", "product_sales_rank": 115167, "product_subcategory": "General", "similar_product_ids": ["B000002RI8", "B00005NQM6", "B000667FXI", "B00020H8Z8", "B0000A0DRX"], "review_helpful_votes": 3} -{"product_id": "0471874388", "customer_id": "A3NYKEMUTB1QEG", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Paul Wilmott on Quantitative Finance, 2 Volume Set", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 256270, "product_subcategory": "Finance", "similar_product_ids": ["0130090565", "0471654647", "0471394203", "0387004513", "0471499226"], "review_helpful_votes": 6} -{"product_id": "B0000296JC", "customer_id": "A3NZSZZORUXTXP", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Make Yourself", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 301940, "product_subcategory": "General", "similar_product_ids": ["B00005QG9J", "B00005RGO5", "B00018D5CQ", "B000050HU9", "B000002BSF"], "review_helpful_votes": 0} -{"product_id": "B00005L9AI", "customer_id": "A3O1W4XSMBT7OZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "010", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 262061, "product_subcategory": "Dance & DJ", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0141802820", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 990849, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} -{"product_id": "0141802847", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 686308, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} -{"product_id": "0451204948", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 28695, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} -{"product_id": "0670896764", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 237651, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} -{"product_id": "B00008RWPR", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Day Late and a Dollar Short", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 118872, "product_subcategory": "World Literature", "similar_product_ids": ["0671884484", "0451205634", "0451192001", "0140116974", "0451194063"], "review_helpful_votes": 3} -{"product_id": "0385471076", "customer_id": "A3O4R2CX4PUGZU", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "A Taste of Power ", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 82450, "product_subcategory": "Ethnic & National", "similar_product_ids": ["1556520743", "0717806677", "038533379X", "080700975X", "1556522304"], "review_helpful_votes": 3} -{"product_id": "B00004U8H5", "customer_id": "A3O4U7KTTGSFOU", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Prenatal Yoga", "review_rating": 5, "product_category": "", "product_sales_rank": 659, "product_subcategory": "", "similar_product_ids": ["B00008J2I7", "B000062XE2", "B00026L8VM", "B00009Y3SX", "B0001FZB6M"], "review_helpful_votes": 13} -{"product_id": "B00004U8H5", "customer_id": "A3O4U7KTTGSFOU", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Prenatal Yoga", "review_rating": 5, "product_category": "", "product_sales_rank": 659, "product_subcategory": "", "similar_product_ids": ["B00008J2I7", "B000062XE2", "B00026L8VM", "B00009Y3SX", "B0001FZB6M"], "review_helpful_votes": 13} -{"product_id": "B00000I9E4", "customer_id": "A3OAQ30458G3GA", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Music", "product_title": "Live at the Sydney Opera House", "review_rating": 4, "product_category": "Pop", "product_sales_rank": 7994, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B0000649PD", "B00000I2GJ", "B00005O6KC", "B00005A8B4", "B000059GIV"], "review_helpful_votes": 9} -{"product_id": "B00005PJCR", "customer_id": "A3OEI0MEVD6C3I", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Audioboxer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 23483, "product_subcategory": "Hardcore & Punk", "similar_product_ids": ["B000091KV8", "B000066B4V", "B0000DD578", "B00065GWKQ", "B00006SFIM"], "review_helpful_votes": 1} -{"product_id": "0312978839", "customer_id": "A3OJ6WLOM4LJNT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Family Reunion", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 605287, "product_subcategory": "General", "similar_product_ids": ["0312315120", "0312306113", "1583145087", "0312989989", "1583141456"], "review_helpful_votes": 1} -{"product_id": "B000001BZQ", "customer_id": "A3ORUKYAHI5X2B", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Follow the Leader", "review_rating": 4, "product_category": "Rap & Hip-Hop", "product_sales_rank": 61989, "product_subcategory": "East Coast", "similar_product_ids": ["B000005HSR", "B000002O75", "B000002OKS", "B000002LEK", "B000003B7B"], "review_helpful_votes": 0} -{"product_id": "0345439945", "customer_id": "A3OZIAYOJ1DNS4", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "100 One-Night Reads ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 256277, "product_subcategory": "Books & Reading", "similar_product_ids": ["0140143505", "1570614350", "1929154178", "1570613818", "0816045585"], "review_helpful_votes": 2} -{"product_id": "B00005QG8W", "customer_id": "A3P214EYY6T8CK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Fake Sound of Progress", "review_rating": 5, "product_category": "Folk", "product_sales_rank": 21319, "product_subcategory": "Traditional British & Celtic Folk", "similar_product_ids": ["B00019PD0W", "B0000C23D6", "B0002A2VS2", "B0000A0WKG", "B00006GF9L"], "review_helpful_votes": 0} -{"product_id": "B00000C2EM", "customer_id": "A3P3GNT2X93PBV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Postcards from Rio", "review_rating": 4, "product_category": "Jazz", "product_sales_rank": 59348, "product_subcategory": "Brazilian Jazz", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "B000001ALS", "customer_id": "A3P68SYSHAB9GD", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Emperors of Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 6457, "product_subcategory": "Classic R&B", "similar_product_ids": ["B000001AKK", "B000001A8J", "B00005NSXV", "B00001QGU7", "0815412185"], "review_helpful_votes": 0} -{"product_id": "B00000DRAD", "customer_id": "A3P6BXE4KG8L5J", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Legendary Masters", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 50049, "product_subcategory": "Oldies", "similar_product_ids": ["B00000I8AJ", "B00005B179", "B00000DRAR", "B000002P1T", "B00000JJAU"], "review_helpful_votes": 0} -{"product_id": "B0000584U2", "customer_id": "A3PAAIPUN554CC", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Relentless Beats", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 109482, "product_subcategory": "General", "similar_product_ids": ["B00005Y1TT", "B00005171U", "B00005UPP4"], "review_helpful_votes": 0} -{"product_id": "1930693931", "customer_id": "A3PB38VN8E5FA4", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "What Color Is Your Scarf?", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 1255218, "product_subcategory": "Relationships", "similar_product_ids": [], "review_helpful_votes": 4} -{"product_id": "B00005A46T", "customer_id": "A3PC0I1XLBDSW", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 4, "product_category": "Hard Rock & Metal", "product_sales_rank": 1154, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B00000JCOV", "B0001NBMBC", "B00004WK3A", "B0000787EO", "B00007BHOE"], "review_helpful_votes": 0} -{"product_id": "B00005NNNG", "customer_id": "A3PC0I1XLBDSW", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Iowa", "review_rating": 4, "product_category": "Hard Rock & Metal", "product_sales_rank": 430847, "product_subcategory": "Alternative Metal", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "B000005IYF", "customer_id": "A3PEMQAM8WICIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Scott Joplin", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 2893, "product_subcategory": "General", "similar_product_ids": ["B000003QWN", "0486258076", "B00000DD02", "B00009PJSR", "B00009PJST"], "review_helpful_votes": 3} -{"product_id": "0140568085", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar! (Picture Puffins)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 268149, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} -{"product_id": "0525452761", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 151545, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} -{"product_id": "0525458344", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 27631, "product_subcategory": "Baby-3", "similar_product_ids": ["0590316818", "0525455914", "0525459057", "1564587185", "0679882014"], "review_helpful_votes": 0} -{"product_id": "0525460888", "customer_id": "A3PG2BEQ2JIBBC", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Dinosaur Roar!", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1793838, "product_subcategory": "Baby-3", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "B00004SVKL", "customer_id": "A3PG5CSK8Y4ECT", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Never Never Land", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 6178, "product_subcategory": "General", "similar_product_ids": ["B00005AWDF", "B0002JP4K0", "B00006G99J", "B0000TSQX4", "B00014X8E0"], "review_helpful_votes": 1} -{"product_id": "0849938635", "customer_id": "A3PK971R04XQAX", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Oath", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 109802, "product_subcategory": "Fiction", "similar_product_ids": ["0849944775", "0842361715", "0891076182", "0891075275", "0849976170"], "review_helpful_votes": 3} -{"product_id": "0849308216", "customer_id": "A3PU1RNZVISZPG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "High-Speed Cisco Networks", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 578941, "product_subcategory": "Certification Central", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "B0000633VJ", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Emergence (Uncut)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 35985, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} -{"product_id": "B0000633VK", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Emergence (Edited)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 62316, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} -{"product_id": "B0000640SV", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "Dragon Ball Z - Majin Buu - Emergence", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 34137, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B0000633S6", "B00005UF7R", "B00005UF7Q", "B0000640SW"], "review_helpful_votes": 9} -{"product_id": "B00005T32J", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Dragon Ball Z - Majin Buu - Defiance (Uncut)", "review_rating": 5, "product_category": "Anime & Manga", "product_sales_rank": 38158, "product_subcategory": "Characters & Series", "similar_product_ids": ["B00005UF7Q", "B0000633S4", "B00005UF7R", "B00005NB92", "B00005K9NY"], "review_helpful_votes": 6} -{"product_id": "B0000633S6", "customer_id": "A3PVTILPPRSN0O", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "DVD", "product_title": "Dragon Ball Z - Majin Buu - Defiance", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 31737, "product_subcategory": "Characters & Series", "similar_product_ids": ["B0000633S4", "B00005UF7R", "B00005NB92", "B0000640SW", "B000066731"], "review_helpful_votes": 6} -{"product_id": "6303991408", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 2880, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} -{"product_id": "B00005TSMN", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4351, "product_subcategory": "Animals", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} -{"product_id": "B00005TSMQ", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 15562, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} -{"product_id": "B00005TSMR", "customer_id": "A3PWQXT5QGEKN7", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Balto Spanish Dubbed", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 3329, "product_subcategory": "Adventure", "similar_product_ids": ["B00005TSMM", "B0006B2A2Y", "0394896955", "0679891986", "6304711913"], "review_helpful_votes": 1} -{"product_id": "B00005V8ST", "customer_id": "A3PXXIO9GJZ1K", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Always Got Tonight", "review_rating": 4, "product_category": "Rock", "product_sales_rank": 14038, "product_subcategory": "General", "similar_product_ids": ["B000002MWG", "B00000AG8O", "B000002LGI", "B000002MH7", "B000002N9X"], "review_helpful_votes": 2} -{"product_id": "B00004SQZG", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Music", "product_title": "Last of the Great 20th Century Composers", "review_rating": 1, "product_category": "Indie Music", "product_sales_rank": 56307, "product_subcategory": "Rap & Hip-Hop", "similar_product_ids": ["B00005NFK7", "B00009KU8F", "B000002JPY", "B00005RTSV", "B00064AEJW"], "review_helpful_votes": 2} -{"product_id": "B00000J7KT", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "The Year of the Backslap", "review_rating": 3, "product_category": "Rap & Hip-Hop", "product_sales_rank": 361395, "product_subcategory": "Gangsta & Hardcore", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "B00004R8PO", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Hip Hop Underground's Finest", "review_rating": 3, "product_category": "Rap & Hip-Hop", "product_sales_rank": 150824, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B0000064SD", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "HII", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 19012, "product_subcategory": "General", "similar_product_ids": ["B000003C04", "B00030EEO0", "B000067CMV", "B00000JG2X", "B0002WZT20"], "review_helpful_votes": 0} -{"product_id": "B00001IVOH", "customer_id": "A3Q7JYFB92ZPJU", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Soul Survivor", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 123928, "product_subcategory": "Rap & Hip-Hop", "similar_product_ids": ["B000002HFW", "B000002H84", "B0000D9Y5N", "B00005AV09", "B000089CGF"], "review_helpful_votes": 0} -{"product_id": "0743442849", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Addicted ", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 4275, "product_subcategory": "Genre Fiction", "similar_product_ids": ["074346270X", "0743457021", "0743476247", "0743482387", "0743442903"], "review_helpful_votes": 0} -{"product_id": "0967460174", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Addicted", "review_rating": 3, "product_category": "Mystery & Thrillers", "product_sales_rank": 801676, "product_subcategory": "Thrillers", "similar_product_ids": ["074346270X", "0743457021", "0743476247", "0743482387", "0743442903"], "review_helpful_votes": 0} -{"product_id": "0375757430", "customer_id": "A3Q7VYG1AOAY5F", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Shades of Jade ", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 167112, "product_subcategory": "Thrillers", "similar_product_ids": ["0870678655", "075820468X", "0375757449", "0967878918", "0743258169"], "review_helpful_votes": 0} -{"product_id": "0060081325", "customer_id": "A3Q80Q6YFP5W6Q", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "A Multitude of Sins", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 890779, "product_subcategory": "General", "similar_product_ids": ["0679776680", "0312423799", "0394757009", "031242227X", "0375726012"], "review_helpful_votes": 10} -{"product_id": "037572656X", "customer_id": "A3Q80Q6YFP5W6Q", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Book", "product_title": "A Multitude of Sins", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 111793, "product_subcategory": "General", "similar_product_ids": ["0679776680", "0312423799", "0394757009", "031242227X", "0375726012"], "review_helpful_votes": 10} -{"product_id": "B000006XCK", "customer_id": "A3Q83VI243WI7U", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "The Byrds [1973]", "review_rating": 4, "product_category": "Classic Rock", "product_sales_rank": 89795, "product_subcategory": "General", "similar_product_ids": ["B00000721Z", "B0001K2LWY", "B00004OCE8", "B0000ACY0Y", "B0001WPSJ0"], "review_helpful_votes": 5} -{"product_id": "031218008X", "customer_id": "A3QBA6UYOZYP3T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "One Thousand White Women ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 54287, "product_subcategory": "Genre Fiction", "similar_product_ids": ["1594480001", "0743227441", "0312422156", "0345416260", "015602943X"], "review_helpful_votes": 3} -{"product_id": "0312199430", "customer_id": "A3QBA6UYOZYP3T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "One Thousand White Women ", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 648, "product_subcategory": "Genre Fiction", "similar_product_ids": ["1594480001", "0743227441", "0312422156", "0345416260", "015602943X"], "review_helpful_votes": 3} -{"product_id": "B000001C6G", "customer_id": "A3QCX67A649QAU", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Eaten Back to Life", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 47079, "product_subcategory": "Death Metal", "similar_product_ids": ["B000001C6W", "B000001C5S", "B000001C7Z", "B0000060ZW", "B000001CAL"], "review_helpful_votes": 2} -{"product_id": "B00004YLAR", "customer_id": "A3QE37MQRFEHYL", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "MIA", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 9741, "product_subcategory": "General", "similar_product_ids": ["B000008EBJ", "B00004YLAP", "B000000LZ2", "B000000JO3", "B000000LXS"], "review_helpful_votes": 1} -{"product_id": "0814471218", "customer_id": "A3QGIY1WPM8LF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Ultimate Web Developer's Sourcebook", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 1126702, "product_subcategory": "Web Development", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0814471218", "customer_id": "A3QGIY1WPM8LF9", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Ultimate Web Developer's Sourcebook", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 1126702, "product_subcategory": "Web Development", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "074323538X", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 2736, "product_subcategory": "Careers", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} -{"product_id": "0743525906", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 383422, "product_subcategory": "Business", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} -{"product_id": "0743525914", "customer_id": "A3QHGZSSC7WT4", "review_date": {"$date": 1013644800000}, "review_votes": 27, "product_group": "Book", "product_title": "Whale Done! ", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 212095, "product_subcategory": "Parenting & Families", "similar_product_ids": ["068815428X", "0786866020", "0688123163", "0688170366", "074325001X"], "review_helpful_votes": 24} -{"product_id": "0071383832", "customer_id": "A3QJE0749PJJJF", "review_date": {"$date": 1013644800000}, "review_votes": 45, "product_group": "Book", "product_title": "The Fat Flush Plan", "review_rating": 4, "product_category": "Health, Mind & Body", "product_sales_rank": 663, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0071407944", "0071433678", "0071440682", "0071414975", "0767920457"], "review_helpful_votes": 44} -{"product_id": "0972488936", "customer_id": "A3QJE0749PJJJF", "review_date": {"$date": 1013644800000}, "review_votes": 45, "product_group": "Book", "product_title": "The Fat Flush Plan", "review_rating": 4, "product_category": "Health, Mind & Body", "product_sales_rank": 113814, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0071407944", "0071433678", "0071440682", "0071414975", "0767920457"], "review_helpful_votes": 44} -{"product_id": "B00002Z845", "customer_id": "A3QLQB0FBL3Q8J", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Hard Volume", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 147708, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B0000040OX", "B0000040P3", "B00002Z847", "B00004KS3P", "B00005NHH9"], "review_helpful_votes": 1} -{"product_id": "0800632753", "customer_id": "A3QVAKVRAH657N", "review_date": {"$date": 1013644800000}, "review_votes": 26, "product_group": "Video", "product_title": "Bonhoeffer - Agent of Grace", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 16895, "product_subcategory": "Leaders & Notable People", "similar_product_ids": ["B0001GH7W2", "B0000ACNPN", "6304267908", "0684838273", "0684815001"], "review_helpful_votes": 25} -{"product_id": "0679721886", "customer_id": "A3QW0OMPL43OHN", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Woman Warrior ", "review_rating": 1, "product_category": "Biographies & Memoirs", "product_sales_rank": 2535, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0679723285", "0140086838", "1577661176", "0814402178", "0295955252"], "review_helpful_votes": 6} -{"product_id": "0808589768", "customer_id": "A3QW0OMPL43OHN", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "The Woman Warrior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 609373, "product_subcategory": "Social Sciences", "similar_product_ids": ["0679723285", "0140086838", "1577661176", "0814402178", "0295955252"], "review_helpful_votes": 6} -{"product_id": "B000003RSB", "customer_id": "A3QWNQ2WA7QZYJ", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Music", "product_title": "Lazer Guided Melodies", "review_rating": 3, "product_category": "Alternative Rock", "product_sales_rank": 40542, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002VUG", "B000002VTE", "B00008WI7A", "B00005OAIL", "B000000EU8"], "review_helpful_votes": 5} -{"product_id": "B00004ZEJH", "customer_id": "A3QWNQ2WA7QZYJ", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Music", "product_title": "Don't Let Go", "review_rating": 3, "product_category": "Rock", "product_sales_rank": 45486, "product_subcategory": "Blues Rock", "similar_product_ids": ["B00005A8B8", "B000002VM1", "B000002VKE", "B0002XEDOE", "B000000XD4"], "review_helpful_votes": 3} -{"product_id": "1569552436", "customer_id": "A3R1FQ5J1279A3", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "Why Do Catholics Genuflect?", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 395217, "product_subcategory": "Christianity", "similar_product_ids": ["0879736933", "0764553917", "0898704782", "0465092624", "0898705533"], "review_helpful_votes": 10} -{"product_id": "6300213714", "customer_id": "A3RC3ORILDUJDN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Warriors", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 6871, "product_subcategory": "General", "similar_product_ids": ["B0000696IC", "B00005NKSN", "0783227876", "B00002E237", "B00004RE45"], "review_helpful_votes": 2} -{"product_id": "B0000541AM", "customer_id": "A3RC3ORILDUJDN", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Warriors", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 1139, "product_subcategory": "General", "similar_product_ids": ["B0000696IC", "B00005NKSN", "0783227876", "B00002E237", "B00004RE45"], "review_helpful_votes": 2} -{"product_id": "0345424719", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 9492, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} -{"product_id": "034543479X", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 413221, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} -{"product_id": "0375501371", "customer_id": "A3RE8WXJBMCNXP", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Widow for One Year ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 461572, "product_subcategory": "General", "similar_product_ids": ["0345361792", "034536676X", "0345387651", "034536743X", "034540047X"], "review_helpful_votes": 2} -{"product_id": "B00005N7AM", "customer_id": "A3REH5JO0KNEUX", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Pat Ortman", "review_rating": 4, "product_category": "Indie Music", "product_sales_rank": 312034, "product_subcategory": "Alternative Rock", "similar_product_ids": [], "review_helpful_votes": 3} -{"product_id": "0521509173", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin (Black Bonded leather)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 201408, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204"], "review_helpful_votes": 5} -{"product_id": "0521509181", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin (Black Calfskin Leather)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 212695, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204", "1400054184"], "review_helpful_votes": 5} -{"product_id": "052150919X", "customer_id": "A3RFDFGJX3UGEM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "KJV Concord Wide Margin Reference Edition with Glossary and Concordance Burgundy calfskin KWM267", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 990503, "product_subcategory": "Christianity", "similar_product_ids": ["0521536960", "0521536987", "0310257204"], "review_helpful_votes": 5} -{"product_id": "1885478747", "customer_id": "A3RT6G1ZAE6WDE", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Fate (Love Spectrum Romance)", "review_rating": 3, "product_category": "Romance", "product_sales_rank": 582828, "product_subcategory": "Multicultural", "similar_product_ids": ["1585710938", "158571108X", "1585710288", "158571092X", "0060747730"], "review_helpful_votes": 2} -{"product_id": "B00005NB9Z", "customer_id": "A3RXXDCXJA1XIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "The Visitors", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 8567, "product_subcategory": "General", "similar_product_ids": ["B00005NB9Y", "B0000A1HQP", "B00005OSLQ", "B00007L4OM", "B0000897B7"], "review_helpful_votes": 3} -{"product_id": "B00005U18K", "customer_id": "A3RXXDCXJA1XIO", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "The Visitors", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 29700, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005NB9Y", "B0000A1HQP", "B00005OSLQ", "B00007L4OM", "B0000897B7"], "review_helpful_votes": 3} -{"product_id": "043936213X", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0590353403", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0786222727", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281751", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281956", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0939173344", "customer_id": "A3S1YIQQW7AZO", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "B00004Z4T0", "customer_id": "A3S5C7Y0WT2Q9N", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Jennifer Lopez - Feelin' So Good", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 11653, "product_subcategory": "General", "similar_product_ids": ["B000087EXR", "B0000DJZ83", "B0000APVH7", "B00005NRO0", "B0000TWMMA"], "review_helpful_votes": 2} -{"product_id": "B00005QFE5", "customer_id": "A3SBVTRU7301II", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Road Home", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 3110, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005JM6H", "0767853512", "B00002RAPT", "B00030590I", "B00004Z1FF"], "review_helpful_votes": 2} -{"product_id": "B00005QFF1", "customer_id": "A3SBVTRU7301II", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Road Home", "review_rating": 5, "product_category": "Art House & International", "product_sales_rank": 1369, "product_subcategory": "By Country", "similar_product_ids": ["B00005JM6H", "0767853512", "B00002RAPT", "B00030590I", "B00004Z1FF"], "review_helpful_votes": 2} -{"product_id": "B00000261W", "customer_id": "A3SFN7ECK78CEV", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Deed Is Done", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 60254, "product_subcategory": "Southern Rock", "similar_product_ids": ["B0000025D5", "B0000025O1", "B000002Z1Q", "B000024PKN"], "review_helpful_votes": 2} -{"product_id": "B000050HZO", "customer_id": "A3SIBP6L8S5KJJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "No Name Face", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 432, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B00006JJ1X", "B0007PALCU", "B00006ALCK", "B00000J6BR", "B00005K9T9"], "review_helpful_votes": 1} -{"product_id": "B000050HZP", "customer_id": "A3SIBP6L8S5KJJ", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "No Name Face", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 333274, "product_subcategory": "Alternative Styles", "similar_product_ids": ["B00006JJ1X", "B0007PALCU", "B00006ALCK", "B00000J6BR", "B00005K9T9"], "review_helpful_votes": 1} -{"product_id": "0140232257", "customer_id": "A3SISHZPSJRA98", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Monster ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 57056, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0060922915", "1587170949", "1556524277", "0385474326", "1576870723"], "review_helpful_votes": 1} -{"product_id": "0735612889", "customer_id": "A3SKXXZKVPCA2T", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Inside C# (With CD-ROM)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 408801, "product_subcategory": "Programming", "similar_product_ids": ["0735615543", "0735614229", "0735613702", "0735612900", "0735619093"], "review_helpful_votes": 2} -{"product_id": "0735616485", "customer_id": "A3SKXXZKVPCA2T", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Inside C#, Second Edition", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 104672, "product_subcategory": "Programming", "similar_product_ids": ["0735615543", "0735614229", "0735613702", "0735612900", "0735619093"], "review_helpful_votes": 2} -{"product_id": "0767908201", "customer_id": "A3SLDKL6UJLK5P", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Inconceivable ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 25732, "product_subcategory": "Specific Groups", "similar_product_ids": ["0316172294", "1893290395", "0684855224", "0142002011", "B0001ARFEI"], "review_helpful_votes": 7} -{"product_id": "006447030X", "customer_id": "A3T79FZYA1SMZ0", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Rifles for Watie", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 65246, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0425102416", "0140341587", "0440442508", "0689715714", "0618250743"], "review_helpful_votes": 5} -{"product_id": "0690049072", "customer_id": "A3T79FZYA1SMZ0", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Rifles for Watie", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 252113, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0140341587", "0425102416", "0440442508", "0689715714", "0618250743"], "review_helpful_votes": 5} -{"product_id": "0060935456", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down (Perennial Classics)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 328957, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} -{"product_id": "0380002930", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 723, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} -{"product_id": "068483605X", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down (Scribner Classics)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 24193, "product_subcategory": "General", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} -{"product_id": "1559352310", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down/Audio Cassettes (Audio csst ed)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 855366, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} -{"product_id": "1565115864", "customer_id": "A3TD858ORCNZX4", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Watership Down Cass", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1121326, "product_subcategory": "General", "similar_product_ids": ["0380729342", "B00005UF84", "0449211827", "B00006G3M1", "1585671827"], "review_helpful_votes": 6} -{"product_id": "1569902089", "customer_id": "A3TMFREIQ35H1X", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Polypropylene Handbook", "review_rating": 4, "product_category": "Engineering", "product_sales_rank": 829140, "product_subcategory": "Chemical", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0393320685", "customer_id": "A3TMFREIQ35H1X", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Chemical Tree", "review_rating": 4, "product_category": "Science", "product_sales_rank": 95053, "product_subcategory": "Chemistry", "similar_product_ids": ["0486233421", "0486659771", "0801866103", "073820594X", "0486610535"], "review_helpful_votes": 2} -{"product_id": "B0000027RL", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Ten", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 1023, "product_subcategory": "General", "similar_product_ids": ["B0000028UK", "B000003TA4", "B000002AZ8", "B000002G2B", "B000002IU3"], "review_helpful_votes": 1} -{"product_id": "0553280414", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 996, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "0553450549", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 622129, "product_subcategory": "Children's Books", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "0684833662", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace (Scribner Classics)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 23067, "product_subcategory": "General", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "0764585789", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace (Cliffs Notes)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 104583, "product_subcategory": "World Literature", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "0791056635", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "John Knowles's a Separate Peace (Bloom's Modern Critical Interpretations)", "review_rating": 5, "product_category": "Reference", "product_sales_rank": 1186382, "product_subcategory": "Education", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "1883332494", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 73885, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "1883332761", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "A Separate Peace", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 204500, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0399501487", "0446310786", "0316769487", "0140177396", "0822011832"], "review_helpful_votes": 0} -{"product_id": "6303503381", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Video", "product_title": "Joseph Campbell and the Power of Myth - Vols. 1-6", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 8275, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["B00005Y71V", "B00005Y71U", "0385418868", "B000063K0N", "0691017840"], "review_helpful_votes": 14} -{"product_id": "B00005MEVQ", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "DVD", "product_title": "Joseph Campbell and the Power of Myth", "review_rating": 5, "product_category": "Special Interests", "product_sales_rank": 1382, "product_subcategory": "General", "similar_product_ids": ["B00005Y71V", "B00005Y71U", "0385418868", "B000063K0N", "0691017840"], "review_helpful_votes": 14} -{"product_id": "0195020588", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The New Oxford Book of American Verse (Oxford Books of Verse)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 439017, "product_subcategory": "Poetry", "similar_product_ids": ["0192141821", "0198121369", "0060540419", "0393041301", "0071427791"], "review_helpful_votes": 1} -{"product_id": "0345335511", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Pawn of Prophecy (The Belgariad, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 21869, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345335457", "0345335708", "0345338715", "0345352661", "0345358805"], "review_helpful_votes": 2} -{"product_id": "0808587226", "customer_id": "A3TMV6SFC9LTWB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Pawn of Prophecy (Belgariad)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 1033362, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0345335457", "0345335708", "0345338715", "0345352661", "0345358805"], "review_helpful_votes": 2} -{"product_id": "B00004WG1R", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "My Favorite Year", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 22977, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} -{"product_id": "B00004WG1S", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "My Favorite Year (Widescreen Edition)", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 20025, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} -{"product_id": "B0000648ZX", "customer_id": "A3TPWQCGMV7KQF", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "My Favorite Year", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 2980, "product_subcategory": "General", "similar_product_ids": ["B00005OCK7", "1573625809", "6305558205", "B000056HEA", "B00005O3V8"], "review_helpful_votes": 4} -{"product_id": "006019832X", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 205543, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} -{"product_id": "006103097X", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 290175, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} -{"product_id": "0066214009", "customer_id": "A3TR2PWA41DBTL", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Hope to Die", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 1243584, "product_subcategory": "Mystery", "similar_product_ids": ["0380725355", "0380713756", "0380806045", "0380725347", "0380709937"], "review_helpful_votes": 3} -{"product_id": "0060987464", "customer_id": "A3TUQDFYUNFXLG", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "The Long Hard Road Out of Hell", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 17997, "product_subcategory": "Arts & Literature", "similar_product_ids": ["0859653293", "B00005U2JL", "B00000AFGM", "B000001Y5X", "B000001Y2U"], "review_helpful_votes": 15} -{"product_id": "0743244281", "customer_id": "A3TXJL518S7UWI", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Barry Trotter and the Unauthorized Parody", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 98495, "product_subcategory": "Humor", "similar_product_ids": ["0451452615", "1593600259", "0671541447", "0972393633", "1571744126"], "review_helpful_votes": 2} -{"product_id": "6302595916", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol (Colorized)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 27980, "product_subcategory": "Fantasy", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "6302914485", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 5394, "product_subcategory": "Adapted from Books", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "B000007P8Z", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 51981, "product_subcategory": "General", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "B000007SXQ", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "A Christmas Carol (50th Anniversary Edition)", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 20384, "product_subcategory": "General", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "B00000F168", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (Colorized Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 14770, "product_subcategory": "3-6 Years", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "B00000JT8Z", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (Original B&W Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4266, "product_subcategory": "7-9 Years", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "B00005TPCG", "customer_id": "A3U1TTMFWN3M5P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "A Christmas Carol (50th Anniversary Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 28748, "product_subcategory": "Family Films", "similar_product_ids": ["B00000K3CK", "B00062J00S", "B00004YNIX", "B00000K3CJ", "B00001TZ6P"], "review_helpful_votes": 2} -{"product_id": "0812522729", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Children of the Night", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 172069, "product_subcategory": "Fantasy", "similar_product_ids": ["0765313170", "0812521145", "0812519655", "0671578057", "0756401615"], "review_helpful_votes": 1} -{"product_id": "031225346X", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Prometheus Deception", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 291444, "product_subcategory": "Thrillers", "similar_product_ids": ["0312982518", "0312989385", "0312973055", "0312981589", "0312982615"], "review_helpful_votes": 1} -{"product_id": "0312978367", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Prometheus Deception", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 38413, "product_subcategory": "Thrillers", "similar_product_ids": ["0312982518", "0312989385", "0312973055", "0312981589", "0553262564"], "review_helpful_votes": 1} -{"product_id": "0886775302", "customer_id": "A3U576SXOYRED6", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Blood Lines (Daw Book Collectors)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 247356, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0060572965", "0060572973", "0425197484", "0553587072", "042519485X"], "review_helpful_votes": 2} -{"product_id": "1579900216", "customer_id": "A3UAAWZH8ESADD", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Laminated Designs in Wood", "review_rating": 5, "product_category": "Home & Garden", "product_sales_rank": 728696, "product_subcategory": "Crafts & Hobbies", "similar_product_ids": [], "review_helpful_votes": 4} -{"product_id": "0804119309", "customer_id": "A3UC0TNMOROOZF", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Last Knight", "review_rating": 5, "product_category": "Romance", "product_sales_rank": 134533, "product_subcategory": "General", "similar_product_ids": ["0804118272", "044900127X", "0804117586", "0804119317", "0345447174"], "review_helpful_votes": 0} -{"product_id": "0768902967", "customer_id": "A3UDY5C0SCQIB9", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Peterson's Scholarships and Loans for Adult Students", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 509257, "product_subcategory": "Education", "similar_product_ids": [], "review_helpful_votes": 7} -{"product_id": "B0000076AV", "customer_id": "A3UH6L4XX59HGX", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Long Riders", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 58143, "product_subcategory": "Blues Rock", "similar_product_ids": ["B000056H2J", "B000002L7L", "B000002N0X", "B000002KCO", "B000002KC4"], "review_helpful_votes": 4} -{"product_id": "1555973140", "customer_id": "A3UHMX027J2Z1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Halls of Fame", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 784305, "product_subcategory": "Social Sciences", "similar_product_ids": ["1555973752", "1555974074", "0970367201", "1555973035", "0880014776"], "review_helpful_votes": 0} -{"product_id": "1555973779", "customer_id": "A3UHMX027J2Z1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Halls of Fame", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 48215, "product_subcategory": "World Literature", "similar_product_ids": ["1555973752", "1555974074", "0970367201", "1555973035", "0880014776"], "review_helpful_votes": 0} -{"product_id": "0385334524", "customer_id": "A3UKGCS3FIO8UD", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Blast from the Past", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 536562, "product_subcategory": "Thrillers", "similar_product_ids": ["0552999458", "0552999954", "0751510114", "0552146986", "0312194722"], "review_helpful_votes": 0} -{"product_id": "0942397061", "customer_id": "A3UKGQ6KRYYRVM", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "God Is My Co-Pilot", "review_rating": 5, "product_category": "", "product_sales_rank": 79442, "product_subcategory": "", "similar_product_ids": ["1560985410", "0394747410", "0440204321", "1574885545", "0671636030"], "review_helpful_votes": 7} -{"product_id": "0064470733", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "One Fat Summer (Ursula Nordstrom Book)", "review_rating": 2, "product_category": "Children's Books", "product_sales_rank": 8461, "product_subcategory": "People & Places", "similar_product_ids": ["0553263218", "0439286034", "0440944597", "0064407314", "0064470393"], "review_helpful_votes": 0} -{"product_id": "0141312351", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 40850, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} -{"product_id": "0525461663", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 432356, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} -{"product_id": "0613359488", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Frightful's Mountain", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 838665, "product_subcategory": "Animals", "similar_product_ids": ["0141312424", "0525469079", "B0001FGBM0", "0064493504", "0064420175"], "review_helpful_votes": 0} -{"product_id": "0440206324", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Island", "review_rating": 3, "product_category": "Teens", "product_sales_rank": 54872, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440413796", "0440407532", "0440227194", "0385746474", "0440219205"], "review_helpful_votes": 0} -{"product_id": "0763607762", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Because of Winn-Dixie)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 8322, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} -{"product_id": "0763616052", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Because of Winn-Dixie)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 528, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} -{"product_id": "0786236655", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie (Thorndike Press Large Print Juvenile Series)", "review_rating": 3, "product_category": "Children's Books", "product_sales_rank": 1193987, "product_subcategory": "Animals", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} -{"product_id": "0807261866", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Because of Winn-Dixie", "review_rating": 3, "product_category": "Books on Tape", "product_sales_rank": 182263, "product_subcategory": "Children's Books", "similar_product_ids": ["0763617229", "0763618985", "0440413281", "0440414806", "0763628441"], "review_helpful_votes": 0} -{"product_id": "6302744679", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Video", "product_title": "Star Trek - The Next Generation, Episode 25", "review_rating": 3, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 44828, "product_subcategory": "Space Adventure", "similar_product_ids": [], "review_helpful_votes": 6} -{"product_id": "0064472345", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Vanishing (Laura Geringer Books (Paperback))", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 144059, "product_subcategory": "People & Places", "similar_product_ids": ["0440415780", "0689866364", "0060502495", "037582233X", "0786851481"], "review_helpful_votes": 0} -{"product_id": "0064472345", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Vanishing (Laura Geringer Books (Paperback))", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 144059, "product_subcategory": "People & Places", "similar_product_ids": ["0440415780", "0689866364", "0060502495", "037582233X", "0786851481"], "review_helpful_votes": 0} -{"product_id": "0152928774", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harris and Me", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 291391, "product_subcategory": "People & Places", "similar_product_ids": ["0440405246", "0440413796", "0440407532", "0440410258", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0316142034", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Snowboard Maverick ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 402792, "product_subcategory": "Sports & Activities", "similar_product_ids": ["0316135127", "0316142417", "0316135496", "0316140023", "0316140538"], "review_helpful_votes": 0} -{"product_id": "0316807222", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee (Newbery Medal Book)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 45196, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0316809063", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 685, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0345370775", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 5356, "product_subcategory": "Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} -{"product_id": "0374378487", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 140908, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480095", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 1401, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480125", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting, 25th Anniversary Edition (Sunburst Book)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 82996, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480133", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 679151, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0385086954", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 78059, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} -{"product_id": "0385325002", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 197367, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} -{"product_id": "0394588169", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 29311, "product_subcategory": "Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} -{"product_id": "0394588304", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jurassic Park", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 466629, "product_subcategory": "Mystery & Thrillers", "similar_product_ids": ["034540288X", "0060541830", "0345417623", "0345353145", "0060541814"], "review_helpful_votes": 0} -{"product_id": "0440227623", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hate You", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 627642, "product_subcategory": "People & Places", "similar_product_ids": ["0066239621", "0385731191", "0385729774", "0439324599", "0689817851"], "review_helpful_votes": 0} -{"product_id": "0440413796", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 24609, "product_subcategory": "Literature", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} -{"product_id": "0553526200", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Brian's Return", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 447812, "product_subcategory": "Children's Books", "similar_product_ids": ["0440227194", "0440407532", "0385746474", "0689826990", "0440407125"], "review_helpful_votes": 0} -{"product_id": "0590366440", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 4, "product_category": "Nonfiction", "product_sales_rank": 809759, "product_subcategory": "Education", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0590373544", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 4, "product_category": "Nonfiction", "product_sales_rank": 734802, "product_subcategory": "Education", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0609810901", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie (Los Jet De Plaza & Janes. Biblioteca De Stephen King. 102, 8)", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1244143, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} -{"product_id": "0671039725", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 72173, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} -{"product_id": "0671039733", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1234187, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} -{"product_id": "0689820836", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Real American Girls Tell Their Own Stories ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 1142523, "product_subcategory": "People & Places", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0805061053", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Both Sides Now", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 881673, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440229219", "0440228794", "0064473473", "014131088X", "0440416027"], "review_helpful_votes": 0} -{"product_id": "0807205958", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 171405, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0807275530", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 393142, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0833585568", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Maniac Magee", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 519286, "product_subcategory": "Literature", "similar_product_ids": ["0440413281", "0440414806", "0064401847", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "1410400204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Heart of the Lonely Exile (An Emerald Ballad, 2)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1385657, "product_subcategory": "General", "similar_product_ids": ["1556611102", "1556611137", "1556611145", "0842314792", "0849943914"], "review_helpful_votes": 0} -{"product_id": "1410400204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Heart of the Lonely Exile (An Emerald Ballad, 2)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 1385657, "product_subcategory": "General", "similar_product_ids": ["1556611102", "1556611137", "1556611145", "0842314792", "0849943914"], "review_helpful_votes": 0} -{"product_id": "1883332648", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 407683, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "8401499666", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Carrie", "review_rating": 4, "product_category": "Horror", "product_sales_rank": 1640707, "product_subcategory": "General", "similar_product_ids": ["0743424425", "0671039741", "0743412273", "0451161351", "0451167805"], "review_helpful_votes": 0} -{"product_id": "0440227623", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hate You", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 627642, "product_subcategory": "People & Places", "similar_product_ids": ["0066239621", "0385731191", "0385729774", "0439324599", "0689817851"], "review_helpful_votes": 0} -{"product_id": "0689206518", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Mrs. Frisby and the Rats of NIMH", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 209256, "product_subcategory": "Animals", "similar_product_ids": ["0064402452", "0440498058", "0689711816", "0064403874", "0064401847"], "review_helpful_votes": 0} -{"product_id": "0689710682", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Mrs. Frisby and the Rats of Nimh (Aladdin Fantasy)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 3351, "product_subcategory": "Animals", "similar_product_ids": ["0064402452", "0440498058", "0689711816", "0064403874", "1557345236"], "review_helpful_votes": 0} -{"product_id": "0027594556", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 54623, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0140366695", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Puffin Classics)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 652238, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0440206324", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Island", "review_rating": 4, "product_category": "Teens", "product_sales_rank": 54872, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440413796", "0440407532", "0440227194", "0385746474", "0440219205"], "review_helpful_votes": 1} -{"product_id": "0448060272", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild and Other Stories (Illustrated Junior Library)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 988203, "product_subcategory": "Literature", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0486264726", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Dover Thrift Editions)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 195561, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0670867969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild (Whole Story)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 400161, "product_subcategory": "Literature", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0812504321", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Call of the Wild ", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 3344, "product_subcategory": "Animals", "similar_product_ids": ["0140366679", "0451527046", "0140390839", "0553212257", "059043053X"], "review_helpful_votes": 1} -{"product_id": "0448089386", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Mystery at Devil's Paw, (Hardy Boys Mystery Stories)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 251103, "product_subcategory": "Literature", "similar_product_ids": ["044808936X", "0448089378", "0448089408", "0448089416", "0448089335"], "review_helpful_votes": 0} -{"product_id": "0152019898", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Captain's Dog", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 498007, "product_subcategory": "Animals", "similar_product_ids": ["1561451908", "0824954424", "0805063684", "1590780280", "1556523742"], "review_helpful_votes": 1} -{"product_id": "0152026967", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Captain's Dog", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 142278, "product_subcategory": "Animals", "similar_product_ids": ["1561451908", "0824954424", "0805063684", "1590780280", "1556523742"], "review_helpful_votes": 1} -{"product_id": "0375759239", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Modern Library Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 207791, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "0486295060", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Dover Thrift Editions)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 176991, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "0486405524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Dover Children's Thrift Classics)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 990009, "product_subcategory": "Literature", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "0486419371", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "War of the Worlds (Dover Large Print Classics)", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 282278, "product_subcategory": "General", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "B0000714I5", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Halloween - Resurrection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 13936, "product_subcategory": "General", "similar_product_ids": ["6305291446", "B00004Y632", "B00005OKQF", "6305971099", "B00005LC4Q"], "review_helpful_votes": 0} -{"product_id": "0553213385", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Bantam Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 67426, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "067103443X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Chocolate-Covered Contest (NANCY DREW ON CAMPUS)", "review_rating": 4, "product_category": "Children's Books", "product_sales_rank": 263954, "product_subcategory": "Literature", "similar_product_ids": ["0671872087", "0743437446", "0671027875", "0671001213", "0671505025"], "review_helpful_votes": 2} -{"product_id": "0688131379", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Books of Wonder)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 148955, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "0812505158", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds (Tor Classics)", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 333, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "0899663761", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "War of the Worlds", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 547989, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0812505042", "0812550927", "0140022651", "0553214322", "0486270718"], "review_helpful_votes": 2} -{"product_id": "1576465128", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The War of the Worlds", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2800303, "product_subcategory": "Authors, A-Z", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "0141306424", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Secret Life of Amanda K. Woods", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 176974, "product_subcategory": "People & Places", "similar_product_ids": ["0689817215", "0439339022", "0439372941", "0064410226", "0763617229"], "review_helpful_votes": 0} -{"product_id": "0316140643", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Football Fugitive (Matt Christopher Sports Classics)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 366780, "product_subcategory": "Sports & Activities", "similar_product_ids": ["0316140775", "0316140589", "0316137952", "0316143073", "0316141674"], "review_helpful_votes": 0} -{"product_id": "0345378490", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Congo", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 548799, "product_subcategory": "Thrillers", "similar_product_ids": ["0345353145", "0345370775", "034540288X", "0345402871", "0060541814"], "review_helpful_votes": 0} -{"product_id": "0374378487", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 140908, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480095", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1401, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480125", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting, 25th Anniversary Edition (Sunburst Book)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82996, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0374480133", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 679151, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0380733021", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "All Alone in the Universe", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 285144, "product_subcategory": "Literature", "similar_product_ids": ["0375829164", "043912042X", "0064405710", "0064405176", "0380713586"], "review_helpful_votes": 0} -{"product_id": "0385303882", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 118084, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0385321414", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} -{"product_id": "0385321414", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 323513, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0064408795", "0060535431"], "review_helpful_votes": 0} -{"product_id": "0399231420", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hope Was Here (Newbery Honor Book)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 73119, "product_subcategory": "Science Fiction & Fantasy", "similar_product_ids": ["0698118286", "037582233X", "0060535431", "014131088X", "0385730586"], "review_helpful_votes": 0} -{"product_id": "0439064864", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0439064864", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0439064872", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 3807, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0439139597", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 327, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0439139600", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 404, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0439203538", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter And The Chamber Of Secrets", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 47934, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0590373544", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 734802, "product_subcategory": "Education", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0439420105", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 151045, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "044022750X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Laurel Leaf Books)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 480132, "product_subcategory": "Literature", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0440407532", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 10728, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0814250858", "customer_id": "A52OMVEGK0MZG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Come Back Irish", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1240223, "product_subcategory": "Short Stories", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0440408032", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Jim Ugly", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 672547, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0440415861", "0440412439", "0440406145", "0689844565", "0141312300"], "review_helpful_votes": 0} -{"product_id": "0440413729", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Belle Prater's Boy", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 57710, "product_subcategory": "People & Places", "similar_product_ids": ["0440413281", "0590371258", "0064405176", "0440414121", "0374308535"], "review_helpful_votes": 0} -{"product_id": "0440418291", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} -{"product_id": "0440418291", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Nory Ryan's Song", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 61455, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0385326580", "0440414539", "0440415780", "0060535431", "0763617229"], "review_helpful_votes": 0} -{"product_id": "0553280082", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Too Young to Die", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 369874, "product_subcategory": "Science, Nature & How It Works", "similar_product_ids": ["0553280074", "0553283499", "0553283502", "0553562657", "0553570900"], "review_helpful_votes": 0} -{"product_id": "0553471287", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 443501, "product_subcategory": "Children's Books", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0590213105", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P.s. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 445386, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116895", "0698116879"], "review_helpful_votes": 0} -{"product_id": "0590213113", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P.s. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 121794, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116879", "0698116895"], "review_helpful_votes": 0} -{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0613182715", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "P. S. Longer Letter Later", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1184225, "product_subcategory": "People & Places", "similar_product_ids": ["0439063353", "0698116844", "0698116909", "0698116879", "0698116895"], "review_helpful_votes": 0} -{"product_id": "0613287142", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Harry Potter (Hardcover))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 122944, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0671505076", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Baby Sitter Burglaries (Nancy Drew on Campus)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 441596, "product_subcategory": "Literature", "similar_product_ids": ["0671001213", "0671000500", "0671505025", "067100753X", "0671872087"], "review_helpful_votes": 0} -{"product_id": "0671751182", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Second Evil (Fear Street Cheerleaders 2)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 292550, "product_subcategory": "Literature", "similar_product_ids": ["0671868357", "0671868314", "0671529722", "0671694111", "0671702440"], "review_helpful_votes": 0} -{"product_id": "0679819460", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Kidnapped At Birth? (Marvin Redpost 1, paper)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 40914, "product_subcategory": "Literature", "similar_product_ids": ["0679819479", "0679819487", "0679819495", "067988999X", "0679890009"], "review_helpful_votes": 0} -{"product_id": "0698119517", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Hope Was Here (2001 Newbery Honor Book)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 7329, "product_subcategory": "Literature", "similar_product_ids": ["0698118286", "037582233X", "0060535431", "014131088X", "0385730586"], "review_helpful_votes": 0} -{"product_id": "0747545774", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1392295, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0786222735", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Thorndike Press Large Print Young Adult Series)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 260444, "product_subcategory": "Literature", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0786229276", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 285760, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0786232196", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Thorndike Press Large Print Young Adult Series)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 506235, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0807275530", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 393142, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281913", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 14389, "product_subcategory": "Children's Books", "similar_product_ids": ["0439139597", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0807281948", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1227, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807282588", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 5031, "product_subcategory": "Children's Books", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807282596", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4 Audio CD) (Harry Potter (J.K. Rowling))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 661, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807286001", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 990191, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807286001", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 990191, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "080728601X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets (Book 2 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1043241, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0833597914", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The River (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 1213829, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440227194", "0440413796", "0689826990", "0385746474", "0440206324"], "review_helpful_votes": 0} -{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0939173352", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Chamber of Secrets, Braille Edition", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 955327, "product_subcategory": "Literature", "similar_product_ids": ["0439139600", "043935806X", "B00005JMAH", "043932162X", "B00008DDXC"], "review_helpful_votes": 0} -{"product_id": "0939173379", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Harry Potter and the Goblet of Fire (Book 4)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 868892, "product_subcategory": "Literature", "similar_product_ids": ["0439136350", "043935806X", "0439064864", "0590353403", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "1567187250", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Teen Witch", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 34955, "product_subcategory": "Earth-Based Religions", "similar_product_ids": ["087542791X", "1567184243", "0738702250", "0738703192", "1567185541"], "review_helpful_votes": 0} -{"product_id": "1883332648", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Tuck Everlasting", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 407683, "product_subcategory": "Literature", "similar_product_ids": ["0064401847", "0440414806", "0440498058", "0440227534", "0440237688"], "review_helpful_votes": 0} -{"product_id": "B00005UT2K", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Soundtracks", "product_sales_rank": 30402, "product_subcategory": "General", "similar_product_ids": ["B00005JKW0", "0446608955", "B0000DG001", "B00005KAVP", "B000089IYW"], "review_helpful_votes": 0} -{"product_id": "0451527747", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Book", "product_title": "Alice's Adventures in Wonderland and Through the Looking Glass", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 3259, "product_subcategory": "World Literature", "similar_product_ids": ["0764587218", "0688166776", "0812523350", "0451527046", "0393048470"], "review_helpful_votes": 6} -{"product_id": "037580207X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Sort of Forever", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 568472, "product_subcategory": "People & Places", "similar_product_ids": ["0141312300", "0689844565", "0440442079", "0590386336", "0689859368"], "review_helpful_votes": 0} -{"product_id": "0380713586", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weasel (Avon Camelot Books (Paperback))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 99122, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["0440466334", "0440227534", "0439286069", "0763616052", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0671025589", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weep No More, My Lady", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 41334, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 0} -{"product_id": "0671657348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "WEEP NO MORE MY LADY", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 254198, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 0} -{"product_id": "0786812249", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Raptor", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 202869, "product_subcategory": "Animals", "similar_product_ids": ["0786813091", "0786810998", "0786812257", "0786812265", "0786851511"], "review_helpful_votes": 0} -{"product_id": "0786823747", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Raptor", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 2353001, "product_subcategory": "Animals", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0788719408", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Weasel", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 1747024, "product_subcategory": "Children's Books", "similar_product_ids": ["0440466334", "0440227534", "0439286069", "0763616052", "0440237688"], "review_helpful_votes": 0} -{"product_id": "0140348107", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 92202, "product_subcategory": "Authors & Illustrators, A-Z", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} -{"product_id": "0141311878", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 311083, "product_subcategory": "Literature", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0141312424", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1549, "product_subcategory": "Literature", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} -{"product_id": "0312857055", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 35312, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} -{"product_id": "0345008634", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (Lord of the Rings (Paperback))", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 302864, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0345339711", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 106662, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "037540872X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember (Random House Large Print)", "review_rating": 5, "product_category": "Large Print", "product_sales_rank": 188319, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "0375728007", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Large Print", "product_sales_rank": 42715, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "0385470819", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 19196, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} -{"product_id": "0395489334", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 187772, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0395732611", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1432267, "product_subcategory": "Literature", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0439221684", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Cry of the Wolf (Avalon, 3)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 620441, "product_subcategory": "Literature", "similar_product_ids": ["0439221706", "0439221714", "0439221730", "1593150032", "1593150113"], "review_helpful_votes": 1} -{"product_id": "0439244021", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Haunted Summer", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 602772, "product_subcategory": "Literature", "similar_product_ids": ["0590436031", "0590436023", "0823405818", "0590434616", "0590029533"], "review_helpful_votes": 1} -{"product_id": "0440211727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 4452, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} -{"product_id": "0446525537", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 12303, "product_subcategory": "General", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "0446608955", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 975, "product_subcategory": "Genre Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "0525463461", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "My Side of the Mountain", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 222791, "product_subcategory": "Literature", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} -{"product_id": "0553470876", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 329688, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "0553502220", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 287390, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} -{"product_id": "0553712640", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Time to Kill", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 406846, "product_subcategory": "Thrillers", "similar_product_ids": ["044021145X", "0440214041", "044022165X", "0440213525", "0440220602"], "review_helpful_votes": 1} -{"product_id": "0590065718", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 282224, "product_subcategory": "Education", "similar_product_ids": ["0141312416", "0141312351", "0440439884", "0689826990", "0553274295"], "review_helpful_votes": 1} -{"product_id": "0590389246", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Literature Guide", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 601085, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "0613281292", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Walk to Remember", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 426989, "product_subcategory": "General", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "0618002235", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 52599, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0618037667", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings (Millennium Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 490274, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} -{"product_id": "0618129081", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 809730, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0618153969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 303145, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} -{"product_id": "0618153977", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 351854, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} -{"product_id": "0618153993", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 803279, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0618260293", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 397199, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 1} -{"product_id": "0618260595", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 243657, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0689808828", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 31079, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "0689826990", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 919, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "0689840926", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 158085, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "0765300273", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 357714, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} -{"product_id": "0765346524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword Of Truth)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 707911, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} -{"product_id": "0671025589", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Weep No More, My Lady", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 41334, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 1} -{"product_id": "0788789546", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Book 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 37606, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "078878983X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (The Lord of the Rings, Book 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 10518, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0812548051", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Sword of Truth, Book 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 12470, "product_subcategory": "Fantasy", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} -{"product_id": "0828810761", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Le Seigneur des Anneaux, Volume 2", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1471165, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "0833508326", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 259781, "product_subcategory": "Literature", "similar_product_ids": ["0440407532", "0440227194", "0440413796", "0385746474", "0440414806"], "review_helpful_votes": 1} -{"product_id": "1561005983", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Wizard's First Rule (Bookcassette(r) Edition)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 497513, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0812548094", "0812551478", "0812551486", "0765340747", "0812551494"], "review_helpful_votes": 1} -{"product_id": "1565116682", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Two Towers (Lord of the Rings Part 2)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 227237, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0345325818", "1594130043", "1594130078", "0439064864"], "review_helpful_votes": 1} -{"product_id": "1570427496", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 176610, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446676098", "0446606812", "0446611867", "0446610399", "0446613436"], "review_helpful_votes": 1} -{"product_id": "1581180551", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Hatchet (Large Print Cornerstone Ser)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 2074340, "product_subcategory": "Literature & Fiction", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B000001ALS", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Emperors of Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 6457, "product_subcategory": "Classic R&B", "similar_product_ids": ["B000001AKK", "B000001A8J", "B00005NSXV", "B00001QGU7", "0815412185"], "review_helpful_votes": 1} -{"product_id": "B00006FD9K", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Godzilla, King of the Monsters", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 13133, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B00006FD9L", "B00006FD9H", "B00003IXDZ", "B00006FD9G", "B00006FD9I"], "review_helpful_votes": 1} -{"product_id": "B00006FDEB", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Godzilla, King of the Monsters", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23813, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B00006FD9H", "B00006FD9L", "B00003IXDZ", "B00006FD9G", "B00006FD9I"], "review_helpful_votes": 1} -{"product_id": "043936213X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0590353403", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0786222727", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281751", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0807281956", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "0939173344", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 0} -{"product_id": "B00004STPK", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Infest", "review_rating": 5, "product_category": "Hard Rock & Metal", "product_sales_rank": 4076, "product_subcategory": "Alternative Metal", "similar_product_ids": ["B000066S03", "B0002TLJEK", "B00000JCB2", "B0002A2VS2", "B00004R7NE"], "review_helpful_votes": 0} -{"product_id": "0440917409", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Deathwatch (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 43345, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0767902459", "0679853065", "0385038283", "0440945151", "0064405648"], "review_helpful_votes": 1} -{"product_id": "0689822294", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Heaven (Coretta Scott King Author Award Winner)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 195922, "product_subcategory": "People & Places", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} -{"product_id": "0689822901", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "HEAVEN", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 68669, "product_subcategory": "People & Places", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} -{"product_id": "0788745638", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Heaven", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 2152840, "product_subcategory": "Children's Books", "similar_product_ids": ["0689849222", "0142501891", "0698119169", "0689818513", "0141307021"], "review_helpful_votes": 1} -{"product_id": "6304507348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "The Blob", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 2991, "product_subcategory": "General", "similar_product_ids": ["0782009980", "B000067FP3", "B0002V7O0Q", "B000063UR0", "B00009NHC0"], "review_helpful_votes": 1} -{"product_id": "B00004W3HE", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "The Blob - Criterion Collection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 6611, "product_subcategory": "General", "similar_product_ids": ["0782009980", "B000067FP3", "B0002V7O0Q", "B000063UR0", "B00004RF9B"], "review_helpful_votes": 1} -{"product_id": "0316606103", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Cirque Du Freak #2", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 112022, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} -{"product_id": "0316606847", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Vampire's Assistant (Cirque du Freak, Book 2)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 81251, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} -{"product_id": "0590434616", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Dollhouse Murders (Apple Chillers)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 63506, "product_subcategory": "Literature", "similar_product_ids": ["0380704420", "0590436031", "0823405818", "0380708655", "0590337041"], "review_helpful_votes": 2} -{"product_id": "0786237341", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Cirque Du Freak", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1481041, "product_subcategory": "Literature", "similar_product_ids": ["0316605107", "0316603953", "0316607096", "0316608068", "0316905747"], "review_helpful_votes": 2} -{"product_id": "B00006LPHA", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Halloween - Resurrection", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 10698, "product_subcategory": "General", "similar_product_ids": ["6305291446", "B00004Y632", "B00005OKQF", "6305971099", "B00005LC4Q"], "review_helpful_votes": 0} -{"product_id": "0671657348", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "WEEP NO MORE MY LADY", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 254198, "product_subcategory": "Mystery", "similar_product_ids": ["0671528203", "0671673688", "0671867091", "0671888587", "0671867156"], "review_helpful_votes": 1} -{"product_id": "0064400670", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Pilot Down, Presumed Dead (Harper Trophy Books (Paperback))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 694441, "product_subcategory": "Literature", "similar_product_ids": ["0064410137", "0064410145"], "review_helpful_votes": 2} -{"product_id": "067168390X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 3357, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} -{"product_id": "0684857529", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 401269, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} -{"product_id": "068487122X", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 41789, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} -{"product_id": "1590400453", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove Vol. 1", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 148345, "product_subcategory": "General", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0684853868"], "review_helpful_votes": 2} -{"product_id": "1590400461", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Lonesome Dove Vol. 2", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 1011576, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0671537466", "0671020641", "0671001167", "B00005Y6YB", "0743451414"], "review_helpful_votes": 2} -{"product_id": "1562477617", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Voices at Whisper Bend (American Girl History Mysteries)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 98930, "product_subcategory": "History & Historical Fiction", "similar_product_ids": ["1562477609", "1562477595", "1562477587", "1562477579", "1584850841"], "review_helpful_votes": 3} -{"product_id": "0385322135", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Voice on the Radio", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 562396, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440220653", "0590988492", "0590474782", "0440219817", "0590457403"], "review_helpful_votes": 0} -{"product_id": "0440219779", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Voice on the Radio (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 40838, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440220653", "0590988492", "0590474782", "0440219817", "0590457403"], "review_helpful_votes": 0} -{"product_id": "0448089270", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Secret of Skull Mountain (Hardy Boys (Hardcover))", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 238160, "product_subcategory": "Literature", "similar_product_ids": ["0448089297", "0448089262", "0448089289", "0448089300", "0448089254"], "review_helpful_votes": 1} -{"product_id": "0788749722", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 183963, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0788749730", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 291336, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842316752", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind (Left Behind #1)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 403684, "product_subcategory": "Religion & Spirituality", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842329110", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 32523, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842329129", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 1388, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842342702", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 353272, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842343237", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Books on CD", "product_sales_rank": 293315, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0842354204", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Left Behind", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 667272, "product_subcategory": "Christianity", "similar_product_ids": ["0842329218", "0842329242", "0842329250", "0842329269", "0842329277"], "review_helpful_votes": 1} -{"product_id": "0618037667", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings (Millennium Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 490274, "product_subcategory": "Fantasy", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} -{"product_id": "0618153969", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 303145, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} -{"product_id": "0618153977", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 351854, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} -{"product_id": "0618260293", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Lord of the Rings", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 397199, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0395177111", "0261103288", "0345325818", "0618260587", "0345375211"], "review_helpful_votes": 3} -{"product_id": "0440978505", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Tex", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 35280, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440975344", "0140389660", "0440204798", "014038572X", "0765305631"], "review_helpful_votes": 4} -{"product_id": "0553258524", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 367389, "product_subcategory": "Fantasy", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} -{"product_id": "0689860080", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 12604, "product_subcategory": "Literature", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} -{"product_id": "0689860234", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy, Volume 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 591788, "product_subcategory": "Literature", "similar_product_ids": ["0345335082", "0345341678", "0345335465", "0345424603", "0345339495"], "review_helpful_votes": 3} -{"product_id": "0881038164", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Dragonsong (Harper Hall Trilogy)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1294458, "product_subcategory": "Fantasy", "similar_product_ids": [], "review_helpful_votes": 3} -{"product_id": "6305818282", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 17697, "product_subcategory": "10-12 Years", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} -{"product_id": "6305818398", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 7638, "product_subcategory": "7-9 Years", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} -{"product_id": "6305848033", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The 10th Kingdom (Extended Play Version)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 10414, "product_subcategory": "Adventure", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} -{"product_id": "B0000648XE", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "DVD", "product_title": "The 10th Kingdom", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 349, "product_subcategory": "Television", "similar_product_ids": ["6305742030", "B00005NB94", "B00005QW5Y", "B00007G1VR", "B00005UW87"], "review_helpful_votes": 7} -{"product_id": "0440207800", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "They Never Came Home (Laurel Leaf Books)", "review_rating": 5, "product_category": "Teens", "product_sales_rank": 131438, "product_subcategory": "Horror", "similar_product_ids": ["0440201845", "0440983568", "0440972922", "044098324X", "0440213428"], "review_helpful_votes": 1} -{"product_id": "0060809027", "customer_id": "A3UN6WX5RRO2AG", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "My Friend Flicka", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 41543, "product_subcategory": "Animals", "similar_product_ids": ["0060809035", "0060809043", "0380810565", "0689714920", "0689714874"], "review_helpful_votes": 8} -{"product_id": "0465091180", "customer_id": "A3UOR2TGAHLVBA", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "We Were Burning ", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 678121, "product_subcategory": "General", "similar_product_ids": ["0804821054", "0066621194"], "review_helpful_votes": 0} -{"product_id": "0883686562", "customer_id": "A3UPT0RGXWHALB", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Thunder in Paradise", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 763391, "product_subcategory": "Christianity", "similar_product_ids": ["0768420997", "0768421608", "0883686295", "0768421772", "0768421748"], "review_helpful_votes": 4} -{"product_id": "B00005B4GT", "customer_id": "A3UQ7P0LMBGD1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Amnesiac", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 262947, "product_subcategory": "British Alternative", "similar_product_ids": ["B00004XONN", "B000092ZYX", "B000002TQV", "B000002UJQ", "B000002UR7"], "review_helpful_votes": 1} -{"product_id": "B00005B4GU", "customer_id": "A3UQ7P0LMBGD1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Amnesiac", "review_rating": 4, "product_category": "Alternative Rock", "product_sales_rank": 1305, "product_subcategory": "British Alternative", "similar_product_ids": ["B00004XONN", "B000092ZYX", "B000002TQV", "B000002UJQ", "B000002UR7"], "review_helpful_votes": 1} -{"product_id": "0735614962", "customer_id": "A3UR8BBCK8AVNM", "review_date": {"$date": 1013644800000}, "review_votes": 19, "product_group": "Book", "product_title": "HIPAA Compliance Solutions", "review_rating": 1, "product_category": "Professional & Technical", "product_sales_rank": 646442, "product_subcategory": "Law", "similar_product_ids": ["B000069F7B", "0735618682", "B00007CI6F"], "review_helpful_votes": 17} -{"product_id": "0842335986", "customer_id": "A3UUSIYN1MR5WJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unspoken (Lineage of Grace Number 4)", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 11978, "product_subcategory": "Fiction", "similar_product_ids": ["0842382658", "1576738167", "0842339523", "0842335714", "0842335684"], "review_helpful_votes": 2} -{"product_id": "158926083X", "customer_id": "A3UUSIYN1MR5WJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unspoken", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 996024, "product_subcategory": "Fiction", "similar_product_ids": ["1576738167", "0842382658", "0842339523", "0842335714", "0842335684"], "review_helpful_votes": 2} -{"product_id": "B00005NNP8", "customer_id": "A3V4CL53QT9X7N", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Music", "product_title": "Barking at Airplanes [Bonus Tracks]", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 23504, "product_subcategory": "Pop Rock", "similar_product_ids": ["B00005NNP9", "B00005NVYE", "B000085RRG", "B00000IAZR", "B000008E14"], "review_helpful_votes": 10} -{"product_id": "0884196755", "customer_id": "A3V4X90KKFW9WU", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Prophetic Etiquette", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 454831, "product_subcategory": "Christianity", "similar_product_ids": ["0884194264", "0768422329", "0800793269", "0830733892", "0310225582"], "review_helpful_votes": 7} -{"product_id": "0412808307", "customer_id": "A3V8W69FK0918O", "review_date": {"$date": 1013644800000}, "review_votes": 19, "product_group": "Book", "product_title": "Introduction to Mathematical Logic, Fourth Edition", "review_rating": 5, "product_category": "Science", "product_sales_rank": 55310, "product_subcategory": "Mathematics", "similar_product_ids": ["0521007585", "0691029067", "0486434753", "0486425339", "0486634620"], "review_helpful_votes": 15} -{"product_id": "B00005U15M", "customer_id": "A3VAD7YDFFQOO5", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "Roger Waters - In the Flesh (Live)", "review_rating": 3, "product_category": "Music Video & Concerts", "product_sales_rank": 36424, "product_subcategory": "General", "similar_product_ids": ["B00006LI4S", "B00009VTYE", "B0000DBJDM", "B0000AOV85", "B0000027I6"], "review_helpful_votes": 1} -{"product_id": "B00005U122", "customer_id": "A3VAD7YDFFQOO5", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "Roger Waters - In the Flesh (Live)", "review_rating": 3, "product_category": "Music Video & Concerts", "product_sales_rank": 3272, "product_subcategory": "General", "similar_product_ids": ["B00006LI4S", "B00009VTYE", "B0000DBJDM", "B0000AOV85", "B0000027I6"], "review_helpful_votes": 1} -{"product_id": "B00005MKTL", "customer_id": "A3VC1M1X0U31N", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Global Underground 21 - Moscow", "review_rating": 2, "product_category": "Indie Music", "product_sales_rank": 43727, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B000095J7T", "B000095J7P", "B00003GNZH", "B00005LN1Y", "B00009Y3QU"], "review_helpful_votes": 2} -{"product_id": "B00005NZK5", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Last Man on Earth", "review_rating": 4, "product_category": "Indie Music", "product_sales_rank": 55129, "product_subcategory": "Folk", "similar_product_ids": ["B0000AKCMI", "B000002US4", "B000006035", "B0007Z9R7U", "B0000004VE"], "review_helpful_votes": 4} -{"product_id": "0745128319", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Book", "product_title": "Blood Sport", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 1027880, "product_subcategory": "Mystery", "similar_product_ids": ["0449221121", "0515125601", "0515124451", "044922113X", "0449221148"], "review_helpful_votes": 5} -{"product_id": "0679735771", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "American Psycho (Vintage Contemporaries)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1301, "product_subcategory": "United States", "similar_product_ids": ["067978148X", "0679781498", "0375703845", "0805076476", "0679743243"], "review_helpful_votes": 0} -{"product_id": "0679735771", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "American Psycho (Vintage Contemporaries)", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 1301, "product_subcategory": "United States", "similar_product_ids": ["067978148X", "0679781498", "0375703845", "0805076476", "0679743243"], "review_helpful_votes": 0} -{"product_id": "0915297019", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "Once a Runner", "review_rating": 5, "product_category": "Sports", "product_sales_rank": 4100, "product_subcategory": "Individual Sports", "similar_product_ids": ["1585743283", "1891369504", "0618391126", "0790739291", "0875964575"], "review_helpful_votes": 0} -{"product_id": "B0000025D0", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Music", "product_title": "Darkness on the Edge of Town", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 2593, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B00000255F", "B0000025KI", "B000002513", "B0000024ZT", "B0000025T6"], "review_helpful_votes": 1} -{"product_id": "B0000025T6", "customer_id": "A3VEG8H36BMBSK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Nebraska", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 1096, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B0007WF1WS", "B000002BFL", "B0000025KI", "B0000025D0", "B00000255F"], "review_helpful_votes": 0} -{"product_id": "B00005UKKE", "customer_id": "A3VHAB1RV9WXLD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Britney Spears - Live from Las Vegas", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 23129, "product_subcategory": "General", "similar_product_ids": ["B000051S4N", "B00064AM62", "B00005RDAF", "B0001BXYUG", "B00002ZMNO"], "review_helpful_votes": 0} -{"product_id": "B00005UKKF", "customer_id": "A3VHAB1RV9WXLD", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Britney Spears - Live from Las Vegas", "review_rating": 5, "product_category": "Music Video & Concerts", "product_sales_rank": 3470, "product_subcategory": "General", "similar_product_ids": ["B000051S4N", "B00064AM62", "B00005RDAF", "B0001BXYUG", "B00002ZMNO"], "review_helpful_votes": 0} -{"product_id": "0783221487", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Dune (Widescreen Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 26397, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} -{"product_id": "0783226063", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Dune", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 9170, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} -{"product_id": "6300183971", "customer_id": "A3VHLKT4OQEZ8L", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Dune", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 6737, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["B0000639EV", "B00008RUYH", "0790729628", "0441172717", "B0000844I8"], "review_helpful_votes": 0} -{"product_id": "0312284330", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 271207, "product_subcategory": "Government", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} -{"product_id": "0312302584", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "Nonfiction", "product_sales_rank": 32795, "product_subcategory": "Government", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} -{"product_id": "B00008RUNJ", "customer_id": "A3VHW9PESLU9RB", "review_date": {"$date": 1013644800000}, "review_votes": 52, "product_group": "Book", "product_title": "Crashing the Party", "review_rating": 3, "product_category": "", "product_sales_rank": 265588, "product_subcategory": "", "similar_product_ids": ["0060756047", "1583220577", "1556431694", "0738208574", "158322629X"], "review_helpful_votes": 21} -{"product_id": "B00000JZC4", "customer_id": "A3VMFN7X82SK5N", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Title of Record", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 11860, "product_subcategory": "General", "similar_product_ids": ["B000002MX5", "B00006916E", "B000009OPW", "B00000IP2T", "B000005ZD3"], "review_helpful_votes": 0} -{"product_id": "6300216802", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Star Trek - The Motion Picture", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23275, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} -{"product_id": "B00005JKHP", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Star Trek - The Motion Picture (The Director's Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 2762, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} -{"product_id": "B00005OLAS", "customer_id": "A3VQSFORKH8B7O", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Star Trek - The Motion Picture (The Director's Edition) (Widescreen)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 8926, "product_subcategory": "General", "similar_product_ids": ["B0000683DH", "B00006G8HX", "B000083C49", "B0000UJL96", "B0000AUHOH"], "review_helpful_votes": 0} -{"product_id": "0807847445", "customer_id": "A3VRBXK9HL8W1W", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Genius of Alexander the Great", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 200965, "product_subcategory": "General", "similar_product_ids": ["0520071662", "0143035134", "0140442537", "1592400531", "0140444122"], "review_helpful_votes": 1} -{"product_id": "0807847445", "customer_id": "A3VRBXK9HL8W1W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Genius of Alexander the Great", "review_rating": 4, "product_category": "Biographies & Memoirs", "product_sales_rank": 200965, "product_subcategory": "General", "similar_product_ids": ["0520071662", "0143035134", "0140442537", "1592400531", "0140444122"], "review_helpful_votes": 1} -{"product_id": "0786607815", "customer_id": "A3VT1HNJOZ33VM", "review_date": {"$date": 1013644800000}, "review_votes": 17, "product_group": "Book", "product_title": "Learning the Tabla Book/CD Set", "review_rating": 5, "product_category": "Entertainment", "product_sales_rank": 38668, "product_subcategory": "Music", "similar_product_ids": ["0964369427", "0963444794", "B000009HRR", "B00005092C", "B00005092O"], "review_helpful_votes": 17} -{"product_id": "0967303524", "customer_id": "A3VZZGNL13I1NR", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Alice at Heart (Waterlilies Series)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 403337, "product_subcategory": "General", "similar_product_ids": ["0967303575", "0446614793", "0425189163", "0446611409", "0446610674"], "review_helpful_votes": 1} -{"product_id": "0803960522", "customer_id": "A3W0IQ8GCH79IE", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Path to School Leadership ", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 416529, "product_subcategory": "Education", "similar_product_ids": ["141290496X", "0761946071"], "review_helpful_votes": 0} -{"product_id": "0971007829", "customer_id": "A3W39HBAEWHRZ8", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Microbranding", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 104209, "product_subcategory": "Economics", "similar_product_ids": ["0446394688", "0814479863", "0793176816", "0385504454", "0814470726"], "review_helpful_votes": 2} -{"product_id": "B00004TH83", "customer_id": "A3X0T82Q0LLDQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Lara Fabian", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 11341, "product_subcategory": "General", "similar_product_ids": ["B000244NK2", "B00004S7L3", "B0000BXGCN", "B00000I2LB", "B00005NW83"], "review_helpful_votes": 3} -{"product_id": "B00004TH84", "customer_id": "A3X0T82Q0LLDQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Lara Fabian [2000]", "review_rating": 3, "product_category": "Pop", "product_sales_rank": 404797, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 3} -{"product_id": "B0000509C4", "customer_id": "A42J5VDT7MHOM", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Creepshow 2", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 9668, "product_subcategory": "General", "similar_product_ids": ["0790744295", "B00005NG6B", "B00006FDCU", "6305972591", "B00004W5UF"], "review_helpful_votes": 1} -{"product_id": "B000059PRW", "customer_id": "A42J5VDT7MHOM", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Creepshow 2", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 35725, "product_subcategory": "General", "similar_product_ids": ["0790744295", "B00005NG6B", "B00006FDCU", "6305972591", "B00004W5UF"], "review_helpful_votes": 1} -{"product_id": "B000000DDJ", "customer_id": "A43756YCL2QPL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "21 Hits Special Collection", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 160377, "product_subcategory": "Pop Rock", "similar_product_ids": ["B000000D5Z"], "review_helpful_votes": 0} -{"product_id": "6303168507", "customer_id": "A46NPO3VKOZPJ", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Schindler's List", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 6967, "product_subcategory": "General", "similar_product_ids": ["B0001NBLVI", "B00005JLT5", "B00028HBKM", "B00003CXCT", "B00003CXA2"], "review_helpful_votes": 1} -{"product_id": "0786708468", "customer_id": "A474FI652OHNI", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Well", "review_rating": 4, "product_category": "Computers & Internet", "product_sales_rank": 646787, "product_subcategory": "Digital Business & Culture", "similar_product_ids": ["0684832674", "0735710759", "0684833484", "0670033820", "0596007191"], "review_helpful_votes": 1} -{"product_id": "0451200438", "customer_id": "A47WXMWXCOGXQ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "The Panic Attack Recovery Book", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 219828, "product_subcategory": "Self-Help", "similar_product_ids": ["0060951605", "0449213315", "0060927585", "089486971X", "0809231026"], "review_helpful_votes": 3} -{"product_id": "0786861037", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Five Equations That Changed the World", "review_rating": 4, "product_category": "Science", "product_sales_rank": 453118, "product_subcategory": "History & Philosophy", "similar_product_ids": ["0785260242", "0874772338", "0486289737", "0385490623", "0195129113"], "review_helpful_votes": 14} -{"product_id": "0786881879", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Five Equations That Changed the World ", "review_rating": 4, "product_category": "Science", "product_sales_rank": 110981, "product_subcategory": "History & Philosophy", "similar_product_ids": ["0785260242", "0874772338", "0486289737", "0385490623", "0195129113"], "review_helpful_votes": 14} -{"product_id": "0486661652", "customer_id": "A4BW129KS5JAD", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Theory and Application of Infinite Series", "review_rating": 4, "product_category": "Science", "product_sales_rank": 48788, "product_subcategory": "Mathematics", "similar_product_ids": ["0486601536", "0486692191", "0486428753", "0521358809", "082182693X"], "review_helpful_votes": 6} -{"product_id": "038550120X", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 111260, "product_subcategory": "General", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} -{"product_id": "044023722X", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Mystery & Thrillers", "product_sales_rank": 1842, "product_subcategory": "Thrillers", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} -{"product_id": "0553502751", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Books on Tape", "product_sales_rank": 217167, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} -{"product_id": "0553712527", "customer_id": "A4EWSHEK2RF49", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "A Painted House", "review_rating": 4, "product_category": "Literature & Fiction", "product_sales_rank": 301752, "product_subcategory": "General", "similar_product_ids": ["0440242002", "0440234743", "0440225701", "0385508417", "0440236673"], "review_helpful_votes": 4} -{"product_id": "B000058DX3", "customer_id": "A4HYUXRZKM33V", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Things We Lost in the Fire", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 27504, "product_subcategory": "General", "similar_product_ids": ["B00006JJ48", "B000777J9G", "B00000IAD0", "B000000A3W", "B000000A42"], "review_helpful_votes": 2} -{"product_id": "B00000JO1Z", "customer_id": "A4SAI3HDIK3UI", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "The Globe Sessions", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 19725, "product_subcategory": "Singer-Songwriters", "similar_product_ids": ["B000002G62", "B0000636UN", "B000002G1T", "B00003L4DJ", "B0000DZ3E2"], "review_helpful_votes": 0} -{"product_id": "0814250858", "customer_id": "A52OMVEGK0MZG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Come Back Irish", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 1240223, "product_subcategory": "Short Stories", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "0446678430", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 1490, "product_subcategory": "Industries & Professions", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} -{"product_id": "1586212559", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich ", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 298115, "product_subcategory": "Personal Finance", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} -{"product_id": "1586212567", "customer_id": "A52RNRXTTT1SQ", "review_date": {"$date": 1013644800000}, "review_votes": 86, "product_group": "Book", "product_title": "Rich Dad's Retire Young, Retire Rich ", "review_rating": 1, "product_category": "Business & Investing", "product_sales_rank": 31034, "product_subcategory": "Personal Finance", "similar_product_ids": ["0446677477", "0446677469", "0446677450", "0446678619", "0446530867"], "review_helpful_votes": 5} -{"product_id": "B00005QD97", "customer_id": "A53VUA1WE6N7I", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Punkzilla", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 108637, "product_subcategory": "General", "similar_product_ids": ["B0000007QS", "B00003TFUH", "B000009CD0", "B000003J1W", "B00005JIYC"], "review_helpful_votes": 1} -{"product_id": "0875420281", "customer_id": "A5427Y1D10XM0", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Animal-Speak", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 2217, "product_subcategory": "Earth-Based Religions", "similar_product_ids": ["1888767340", "1888767480", "0312204914", "0875420087", "1888767057"], "review_helpful_votes": 15} -{"product_id": "0971260109", "customer_id": "A56LLILL8LK4K", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "This is NOT Brain Surgery! A Mental Health Companion for the Gastric Bypass Patient", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 822230, "product_subcategory": "Mental Health", "similar_product_ids": [], "review_helpful_votes": 4} -{"product_id": "0345413881", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death (Alex Delaware)", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 18042, "product_subcategory": "Police Procedurals", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} -{"product_id": "0679459618", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death ", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 326385, "product_subcategory": "Police Procedurals", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} -{"product_id": "B00007D040", "customer_id": "A58O0C2U6X1NB", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Dr. Death", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 119528, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0345413873", "034541389X", "0345458842", "034546074X", "0345458834"], "review_helpful_votes": 3} -{"product_id": "0140707018", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (New Penguin Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 527022, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} -{"product_id": "0140714847", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (The Pelican Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 258951, "product_subcategory": "World Literature", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0174436041", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1077810, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0451526864", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "The Tragedy of Romeo and Juliet (Signet Classic, 2686)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 87072, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0460871773", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Everyman's Library (Paper))", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1132378, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "B00005PJ8E", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Quills", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 20748, "product_subcategory": "Period Piece", "similar_product_ids": ["B00003CWRC", "B000056BSF", "B00007AJFB", "B0000E32V0", "076781777X"], "review_helpful_votes": 2} -{"product_id": "0521294053", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (The New Cambridge Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 1217567, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0521634970", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Cambridge School Shakespeare)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 110729, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0553213059", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet (Bantam Classic)", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 350348, "product_subcategory": "Drama", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0521787289", "0140177396"], "review_helpful_votes": 1} -{"product_id": "0671722859", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "ROMEO AND JULIET", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 238088, "product_subcategory": "General", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} -{"product_id": "089845980X", "customer_id": "A59LURUK6I2TB", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Romeo and Juliet", "review_rating": 3, "product_category": "Literature & Fiction", "product_sales_rank": 454364, "product_subcategory": "World Literature", "similar_product_ids": ["0486290972", "0764585924", "0399501487", "0140177396", "0521787289"], "review_helpful_votes": 1} -{"product_id": "B00005UPFI", "customer_id": "A5GJXZCBM6F3G", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Music", "product_title": "Greatest Love Songs", "review_rating": 4, "product_category": "Pop", "product_sales_rank": 4372, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B00007LTI5", "B000002NFI", "B0000479AV", "B000002LOI", "B000002AJH"], "review_helpful_votes": 8} -{"product_id": "0312181531", "customer_id": "A5GMDKHEW3R9F", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "An Original Man ", "review_rating": 5, "product_category": "Biographies & Memoirs", "product_sales_rank": 55620, "product_subcategory": "Ethnic & National", "similar_product_ids": ["0875524745", "067944260X", "1884855237", "1884855210", "188485513X"], "review_helpful_votes": 1} -{"product_id": "0609808052", "customer_id": "A5GRFTMJYEHYP", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Tagbook ", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 955586, "product_subcategory": "Social Sciences", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "6305428220", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Faculty", "review_rating": 5, "product_category": "Horror", "product_sales_rank": 2156, "product_subcategory": "General", "similar_product_ids": ["0792840127", "0780631684", "B00004W20F", "B0006J28KK", "B00002RB4P"], "review_helpful_votes": 1} -{"product_id": "B00000IO4J", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "The Faculty", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 15606, "product_subcategory": "General", "similar_product_ids": ["0792840127", "0780631684", "B00004W20F", "B0006J28KK", "B00002RB4P"], "review_helpful_votes": 1} -{"product_id": "0790731916", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Forever Young", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 5606, "product_subcategory": "General", "similar_product_ids": ["B00019073K", "0790731940", "6304708793", "0783233507", "0783227396"], "review_helpful_votes": 1} -{"product_id": "079074015X", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Forever Young", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 12625, "product_subcategory": "General", "similar_product_ids": ["B00019073K", "0790731940", "0783233507", "6304708793", "0783227396"], "review_helpful_votes": 1} -{"product_id": "6305219931", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Forever Young", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 101058, "product_subcategory": "Fantasy", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "630300203X", "customer_id": "A5GZBWOBDADAG", "review_date": {"$date": 1013644800000}, "review_votes": 7, "product_group": "Video", "product_title": "The Good Son", "review_rating": 5, "product_category": "Mystery & Suspense", "product_sales_rank": 16175, "product_subcategory": "Suspense", "similar_product_ids": ["0783233507", "B0002TSZI8", "B0001I55V0", "B0000VV512", "B00005TPMM"], "review_helpful_votes": 5} -{"product_id": "0375501932", "customer_id": "A5KB7UIU6ZUL6", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "Nancy Silverton's Pastries from the La Brea Bakery", "review_rating": 1, "product_category": "Cooking, Food & Wine", "product_sales_rank": 39306, "product_subcategory": "Baking", "similar_product_ids": ["0679409076", "0375412603", "0618138927", "0061817708", "0517224909"], "review_helpful_votes": 3} -{"product_id": "0679409076", "customer_id": "A5KB7UIU6ZUL6", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Nancy Silverton's Breads from the La Brea Bakery ", "review_rating": 1, "product_category": "Cooking, Food & Wine", "product_sales_rank": 39814, "product_subcategory": "Baking", "similar_product_ids": ["0375501932", "1580082688", "1580080030", "0898159164", "1579651178"], "review_helpful_votes": 2} -{"product_id": "B000001I0E", "customer_id": "A5KJVGJ43ZDC9", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Bad Music for Bad People", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 17062, "product_subcategory": "General", "similar_product_ids": ["B000001I0K", "B00005O7W8", "B000001I09", "B000002L31", "B00005O7W6"], "review_helpful_votes": 2} -{"product_id": "0060007834", "customer_id": "A5MPR38KL612P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unnatural Fire ", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 514607, "product_subcategory": "Mystery", "similar_product_ids": ["0060522062", "0375508554", "075284475X", "0340793325", "081257236X"], "review_helpful_votes": 2} -{"product_id": "0688176836", "customer_id": "A5MPR38KL612P", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Unnatural Fire", "review_rating": 5, "product_category": "Mystery & Thrillers", "product_sales_rank": 630471, "product_subcategory": "Mystery", "similar_product_ids": ["0060522062", "0375508554", "075284475X", "0340793325", "081257236X"], "review_helpful_votes": 2} -{"product_id": "B000002564", "customer_id": "A5PP5IRQDVZSG", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Silk Degrees", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 1975, "product_subcategory": "Soft Rock", "similar_product_ids": ["B00000252C", "B0000025KC", "B0000025A2", "B000089HC7", "B00000DCGY"], "review_helpful_votes": 1} -{"product_id": "B00005QG8W", "customer_id": "A61CGWLOIZJ7V", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Fake Sound of Progress", "review_rating": 5, "product_category": "Folk", "product_sales_rank": 21319, "product_subcategory": "Traditional British & Celtic Folk", "similar_product_ids": ["B00019PD0W", "B0000C23D6", "B0002A2VS2", "B0000A0WKG", "B00006GF9L"], "review_helpful_votes": 0} -{"product_id": "0671318489", "customer_id": "A61VICZMFN9RU", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Shiva Option", "review_rating": 4, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 338568, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["0671877798", "0671720244", "0671721119", "0743488520", "074349881X"], "review_helpful_votes": 2} -{"product_id": "B000003BEU", "customer_id": "A62FJDQG6SJNL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Their Satanic Majesties Request", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 446718, "product_subcategory": "Supergroups", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "B000003BEV", "customer_id": "A62FJDQG6SJNL", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Satanic Majesties Request", "review_rating": 3, "product_category": "Classic Rock", "product_sales_rank": 27458, "product_subcategory": "Psychedelic Rock", "similar_product_ids": ["B000003BEM", "B000003BEG", "B000003BDY", "B000003BEA", "B00006AW2T"], "review_helpful_votes": 0} -{"product_id": "0671316486", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In The Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 140220, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} -{"product_id": "0671582828", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In The Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 191127, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} -{"product_id": "0684841363", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "IN THE MEANTIME ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 57125, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} -{"product_id": "0684848066", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In the Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 3096, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} -{"product_id": "068487072X", "customer_id": "A64QC8PS16RVG", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "In the Meantime ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 1122795, "product_subcategory": "Relationships", "similar_product_ids": ["0743227107", "0684867486", "0684841347", "0684859971", "0684869837"], "review_helpful_votes": 3} -{"product_id": "B00004TX01", "customer_id": "A6EKTPVKZ41DJ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Caged Combat - Kiev, Ukraine", "review_rating": 4, "product_category": "Sports", "product_sales_rank": 49783, "product_subcategory": "Wrestling", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0252067959", "customer_id": "A6G57DQXL28RQ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Cyber-Marx", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 557473, "product_subcategory": "Economics", "similar_product_ids": ["1583670882", "1594200246", "1859843301", "0745316069", "0262692333"], "review_helpful_votes": 5} -{"product_id": "0873891511", "customer_id": "A6J9LEDY715BA", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Creating a Customer-Centered Culture", "review_rating": 5, "product_category": "Business & Investing", "product_sales_rank": 282962, "product_subcategory": "General", "similar_product_ids": ["0201608138", "0201154935", "1563273012", "0972572805", "1578512549"], "review_helpful_votes": 1} -{"product_id": "1861542119", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "Jam", "review_rating": 2, "product_category": "Arts & Photography", "product_sales_rank": 149197, "product_subcategory": "Graphic Design", "similar_product_ids": ["1895497493", "081184255X", "3775712542", "1891024604", "0810967022"], "review_helpful_votes": 6} -{"product_id": "0821224638", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "The Essential Duane Michals", "review_rating": 3, "product_category": "Arts & Photography", "product_sales_rank": 448609, "product_subcategory": "Photography", "similar_product_ids": ["0944092861", "1900564734", "0944092349", "1931788340", "082122459X"], "review_helpful_votes": 1} -{"product_id": "0802137598", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Pocket Canons 10-copy Boxed Set", "review_rating": 4, "product_category": "Religion & Spirituality", "product_sales_rank": 366526, "product_subcategory": "Christianity", "similar_product_ids": ["0192834118", "0802136095"], "review_helpful_votes": 1} -{"product_id": "0714834831", "customer_id": "A6LPQMX2YW77O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Michelangelo (art and ideas)", "review_rating": 5, "product_category": "Arts & Photography", "product_sales_rank": 367257, "product_subcategory": "Art", "similar_product_ids": ["019283410X", "0192837702", "0812091752", "0812094263", "0812019997"], "review_helpful_votes": 3} -{"product_id": "B000002BHE", "customer_id": "A6P74FB5ZXMW8", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Music", "product_title": "Falling into You", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 3034, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B000002C4J", "B0000029DQ", "B000031XCR", "B00005YXZI", "B0000028M4"], "review_helpful_votes": 3} -{"product_id": "0767002652", "customer_id": "A6QA74AASV8RM", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Video", "product_title": "Upstairs Downstairs - The Premiere Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 4869, "product_subcategory": "TV Series", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 3} -{"product_id": "B00005NKCM", "customer_id": "A6QA74AASV8RM", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Upstairs Downstairs - The Complete First Season", "review_rating": 5, "product_category": "Television", "product_sales_rank": 5806, "product_subcategory": "A&E Home Video", "similar_product_ids": ["B00005U8F0", "B000062XDM", "B000068QOC", "B000068QOD", "B00005JLG2"], "review_helpful_votes": 3} -{"product_id": "B000002HMH", "customer_id": "A6RK21XAAVHJ5", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Load", "review_rating": 2, "product_category": "Hard Rock & Metal", "product_sales_rank": 2474, "product_subcategory": "General", "similar_product_ids": ["B000002HRE", "B000002H97", "B000002H33", "B000002H2H", "B000002H6C"], "review_helpful_votes": 3} -{"product_id": "B000025JVE", "customer_id": "A6RK21XAAVHJ5", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Victims of the Future", "review_rating": 4, "product_category": "Classic Rock", "product_sales_rank": 65235, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": [], "review_helpful_votes": 0} -{"product_id": "0735201609", "customer_id": "A6SHVHC69ERT2", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "How to Make Million$ in Real Estate in Three Years Startingwith No Cash, Third Edition", "review_rating": 2, "product_category": "Business & Investing", "product_sales_rank": 36595, "product_subcategory": "General", "similar_product_ids": ["0735201161", "0471464996", "0793173655", "0793144914", "0071373373"], "review_helpful_votes": 2} -{"product_id": "B00005RFAI", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Missundaztood", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 2800, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "B00005RGI0", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 242158, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "B00005UW47", "customer_id": "A6TS0YFHZYZMK", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood [German Bonus Track]", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 112988, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "193184125X", "customer_id": "A7974HWVHZMNH", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "Visual Basic Game Programming with DirectX (The Premier Press Game Development Series)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 188449, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["0789725924", "0672322250", "0471355992", "1592000096", "1590594010"], "review_helpful_votes": 2} -{"product_id": "B00003CXI0", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 280, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B00003CXI1", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Special Widescreen Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 337, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B000062TU1", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone (Full Screen Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 1576, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B000062TU2", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone - Spanish Edition", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 4207, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B00006IRHA", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 40700, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B00006IRHB", "customer_id": "A7CORSWQCEGO2", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Video", "product_title": "Harry Potter and the Sorcerer's Stone Gift Set With Fluffy Collectible", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 33519, "product_subcategory": "Adventure", "similar_product_ids": ["B00008DDXC", "B00005JMAH", "B00005JMQZ", "B000634DCW", "B000067DNF"], "review_helpful_votes": 2} -{"product_id": "B00003CXHJ", "customer_id": "A7DPX5TBE8V1O", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "U-571 (Collector's Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 4304, "product_subcategory": "General", "similar_product_ids": ["B00005JLGJ", "0767802470", "B00008K76U", "6304765258", "B00003CXRA"], "review_helpful_votes": 4} -{"product_id": "B00005B6N7", "customer_id": "A7DPX5TBE8V1O", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Video", "product_title": "U-571", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 10126, "product_subcategory": "General", "similar_product_ids": ["B00005JLGJ", "0767802470", "B00008K76U", "6304765258", "B00003CXRA"], "review_helpful_votes": 4} -{"product_id": "B00004WKDD", "customer_id": "A7EAZIPQAVNYZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "Mechmetio", "review_rating": 5, "product_category": "International", "product_sales_rank": 31228, "product_subcategory": "Europe", "similar_product_ids": ["B000005IZA", "B00004YL4I", "B0000034AU", "B000005IW5", "B00005R1PX"], "review_helpful_votes": 0} -{"product_id": "0830813241", "customer_id": "A7EE5ZR41SX5O", "review_date": {"$date": 1013644800000}, "review_votes": 25, "product_group": "Book", "product_title": "Darwin on Trial", "review_rating": 5, "product_category": "Religion & Spirituality", "product_sales_rank": 33339, "product_subcategory": "Christianity", "similar_product_ids": ["0684834936", "0830813608", "091756152X", "0895262002", "0830819290"], "review_helpful_votes": 14} -{"product_id": "6303695779", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Vampyr", "review_rating": 1, "product_category": "Art House & International", "product_sales_rank": 41791, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005O5CA", "0780022343", "B00005M2C7", "6305075492", "B0002NRS46"], "review_helpful_votes": 1} -{"product_id": "6305078491", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Vampyr", "review_rating": 1, "product_category": "Art House & International", "product_sales_rank": 25577, "product_subcategory": "By Original Language", "similar_product_ids": ["B00005O5CA", "0780022343", "B00005M2C7", "6305075492", "B0002NRS46"], "review_helpful_votes": 1} -{"product_id": "B0000029K1", "customer_id": "A7OBFVHNJGI2A", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "A Gene Autry Christmas", "review_rating": 3, "product_category": "Country", "product_sales_rank": 187588, "product_subcategory": "Cowboy", "similar_product_ids": [], "review_helpful_votes": 2} -{"product_id": "B000053V8F", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Frank Herbert's Dune (TV Miniseries)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 24691, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} -{"product_id": "B00005O5BA", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Frank Herbert's Dune (TV Miniseries)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 32035, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} -{"product_id": "B00005O5H0", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Frank Herbert's Dune (TV Miniseries) (EP Version)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 13897, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441172717"], "review_helpful_votes": 0} -{"product_id": "B0000639EV", "customer_id": "A7PBI5HADJYER", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Frank Herbert's Dune (TV Miniseries) (Director's Cut Special Edition)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 1323, "product_subcategory": "Sci-Fi Action", "similar_product_ids": ["0783226063", "B00064AFBE", "0441172695", "0441104029", "0441294677"], "review_helpful_votes": 0} -{"product_id": "B00005R87Q", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "The Fast and the Furious", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 3417, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00008EYA5"], "review_helpful_votes": 0} -{"product_id": "B000063USY", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Video", "product_title": "The Fast and the Furious", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 14370, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00008EYA5"], "review_helpful_votes": 0} -{"product_id": "B00008MZ0N", "customer_id": "A7QHLYRUHYT8I", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "The Fast and the Furious (Widescreen Tricked Out Edition)", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 4968, "product_subcategory": "Crime", "similar_product_ids": ["B00005JM4Z", "B00005JL3K", "B00004Z4WR", "B00009ZPUA", "B00007LB4C"], "review_helpful_votes": 0} -{"product_id": "0764550381", "customer_id": "A7W44JUDEZC44", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "House Selling for Dummies", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 168383, "product_subcategory": "General", "similar_product_ids": ["0764553313", "0609809334", "0793150264", "0517888440", "097073462X"], "review_helpful_votes": 19} -{"product_id": "0764554255", "customer_id": "A7W44JUDEZC44", "review_date": {"$date": 1013644800000}, "review_votes": 21, "product_group": "Book", "product_title": "House Selling for Dummies", "review_rating": 4, "product_category": "Business & Investing", "product_sales_rank": 6220, "product_subcategory": "General", "similar_product_ids": ["0764553313", "0609809334", "0793150264", "0517888440", "097073462X"], "review_helpful_votes": 19} -{"product_id": "0786862181", "customer_id": "A817ZFWX0NMXC", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Surrendering to Marriage", "review_rating": 5, "product_category": "Nonfiction", "product_sales_rank": 309264, "product_subcategory": "Social Sciences", "similar_product_ids": ["0786869135", "0786883189", "0312254709", "0767900421", "0743210808"], "review_helpful_votes": 6} -{"product_id": "0786887710", "customer_id": "A817ZFWX0NMXC", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Book", "product_title": "Surrendering to Marriage ", "review_rating": 5, "product_category": "Health, Mind & Body", "product_sales_rank": 172900, "product_subcategory": "Relationships", "similar_product_ids": ["0786869135", "0786883189", "0312254709", "0767900421", "0743210808"], "review_helpful_votes": 6} -{"product_id": "B000053VB4", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "DVD", "product_title": "Mystic Pizza", "review_rating": 1, "product_category": "Drama", "product_sales_rank": 5388, "product_subcategory": "General", "similar_product_ids": ["6305696071", "B00002ND7J", "B00003CXFV", "B00004TJKK", "0767821769"], "review_helpful_votes": 4} -{"product_id": "B000053VDQ", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 12, "product_group": "Video", "product_title": "Mystic Pizza", "review_rating": 1, "product_category": "Drama", "product_sales_rank": 5474, "product_subcategory": "General", "similar_product_ids": ["6305696071", "B00002ND7J", "B00003CXFV", "B00004TJKK", "0767821769"], "review_helpful_votes": 4} -{"product_id": "6303675034", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Pump up the Volume", "review_rating": 2, "product_category": "Drama", "product_sales_rank": 16171, "product_subcategory": "General", "similar_product_ids": ["B000059PPG", "B00009AOBM", "B000002O8M", "B00006FDCF", "B00003CXCI"], "review_helpful_votes": 6} -{"product_id": "B000031EG0", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "DVD", "product_title": "Pump up the Volume", "review_rating": 2, "product_category": "Art House & International", "product_sales_rank": 6630, "product_subcategory": "By Country", "similar_product_ids": ["B000059PPG", "B00009AOBM", "B000002O8M", "B00006FDCF", "B00003CXCI"], "review_helpful_votes": 6} -{"product_id": "B00003CXPV", "customer_id": "A84UFSF2SZS2W", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "DVD", "product_title": "Quills", "review_rating": 4, "product_category": "Drama", "product_sales_rank": 7892, "product_subcategory": "General", "similar_product_ids": ["B00003CWRC", "B000056BSF", "B00007AJFB", "B0000E32V0", "076781777X"], "review_helpful_votes": 2} -{"product_id": "B00005Q6NP", "customer_id": "A8BROR21R5NPM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Innocence & Despair", "review_rating": 3, "product_category": "Indie Music", "product_sales_rank": 39804, "product_subcategory": "Miscellaneous", "similar_product_ids": ["B00006NSX1", "B000087DRX", "B000077SX3", "1556523726", "B000003F97"], "review_helpful_votes": 3} -{"product_id": "0786915528", "customer_id": "A8IZXBE7J6RNJ", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "Monster Manual", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 15172, "product_subcategory": "Fantasy", "similar_product_ids": ["078691551X", "0786915501", "0786918454", "0786926538", "0786928735"], "review_helpful_votes": 2} -{"product_id": "B00005UT2K", "customer_id": "A8OAEO4POY0JN", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Music", "product_title": "A Walk to Remember", "review_rating": 5, "product_category": "Soundtracks", "product_sales_rank": 30402, "product_subcategory": "General", "similar_product_ids": ["B00005JKW0", "0446608955", "B0000DG001", "B00005KAVP", "B000089IYW"], "review_helpful_votes": 0} -{"product_id": "1892890062", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Beauty of Horses - Horse Lover's Library, Vol. 1 (Screen-A-Day-Calendar) (60-Second Smart)", "review_rating": 3, "product_category": "Calendars", "product_sales_rank": 1453843, "product_subcategory": "Block Calendars", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "043936213X", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 347636, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "0590353403", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 170, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "0786222727", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Large Print)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 82498, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "0807281751", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1, Audio)", "review_rating": 5, "product_category": "Books on Tape", "product_sales_rank": 6496, "product_subcategory": "Children's Books", "similar_product_ids": ["0439064864", "0439136350", "0439139597", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "0807281956", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone (Book 1 Audio CD)", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 1533, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "0939173344", "customer_id": "A8OPBQX4F5TZ6", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "Harry Potter and the Sorcerer's Stone", "review_rating": 5, "product_category": "Children's Books", "product_sales_rank": 685119, "product_subcategory": "Literature", "similar_product_ids": ["0439064864", "0439136350", "0439139600", "043935806X", "B00005JMAH"], "review_helpful_votes": 1} -{"product_id": "B000001DYA", "customer_id": "A8OQZV538BU1Y", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Vincebus Eruptum", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 33775, "product_subcategory": "Psychedelic Rock", "similar_product_ids": ["B000001DY9", "B000005IS1", "B000003CMR", "B00004WGY4", "B000002IAK"], "review_helpful_votes": 2} -{"product_id": "B000002UJQ", "customer_id": "A8RQSDCLE1JF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Ok Computer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 160, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002TQV", "B00004XONN", "B000092ZYX", "B00005B4GU", "B000002UR7"], "review_helpful_votes": 1} -{"product_id": "B000002UJR", "customer_id": "A8RQSDCLE1JF9", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "OK Computer", "review_rating": 5, "product_category": "Alternative Rock", "product_sales_rank": 228214, "product_subcategory": "British Alternative", "similar_product_ids": ["B000002TQV", "B00004XONN", "B000092ZYX", "B00005B4GU", "B000002UR7"], "review_helpful_votes": 1} -{"product_id": "6304711921", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Nightmare Before Christmas", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 41051, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} -{"product_id": "6305949972", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "The Nightmare Before Christmas - Special Edition (Widescreen)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 7112, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} -{"product_id": "6305949980", "customer_id": "A8USMU4Z9IB50", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Nightmare Before Christmas (Special Edition)", "review_rating": 5, "product_category": "Kids & Family", "product_sales_rank": 443, "product_subcategory": "Animation", "similar_product_ids": ["B00004U8P8", "0790731479", "B000001M1W", "B00005JMAH", "630595027X"], "review_helpful_votes": 1} -{"product_id": "B00005UDE3", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 13, "product_group": "Music", "product_title": "Big Generator", "review_rating": 4, "product_category": "Rock", "product_sales_rank": 231090, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B00005B19Z", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "More You Know", "review_rating": 5, "product_category": "Indie Music", "product_sales_rank": 323171, "product_subcategory": "Rock", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B00005NWMK", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Magnification", "review_rating": 5, "product_category": "Classic Rock", "product_sales_rank": 72433, "product_subcategory": "Album-Oriented Rock (AOR)", "similar_product_ids": ["B00001O2V8", "B000069KGN", "B000005CG0", "B000001Y9T", "B00005YUNY"], "review_helpful_votes": 1} -{"product_id": "B000066I3R", "customer_id": "A8WRYXKY9L80O", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Music", "product_title": "Magnification", "review_rating": 5, "product_category": "Rock", "product_sales_rank": 156115, "product_subcategory": "Progressive", "similar_product_ids": ["B00001O2V8", "B000069KGN", "B000005CG0", "B00005YUNY", "B000001Y9T"], "review_helpful_votes": 1} -{"product_id": "031287717X", "customer_id": "A9304G3R4X8LT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Wayfarer Redemption, Book 1", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 387550, "product_subcategory": "Fantasy", "similar_product_ids": ["0765341964", "0765342812", "0312870469", "0732259320", "0765344424"], "review_helpful_votes": 0} -{"product_id": "0765341301", "customer_id": "A9304G3R4X8LT", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Book", "product_title": "The Wayfarer Redemption (The Axis Trilogy, Bk 1)", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 111008, "product_subcategory": "Fantasy", "similar_product_ids": ["0765341964", "0765342812", "0312870469", "0732259320", "0765344424"], "review_helpful_votes": 0} -{"product_id": "B00004XMSB", "customer_id": "A9B7MPB3BMF8I", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "Video", "product_title": "Hercules in New York", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 23503, "product_subcategory": "General", "similar_product_ids": ["B0000C3I6U", "B00013RC8E", "B00018YC3M", "B000063INF", "B0001Z37HM"], "review_helpful_votes": 14} -{"product_id": "B00004XMSC", "customer_id": "A9B7MPB3BMF8I", "review_date": {"$date": 1013644800000}, "review_votes": 14, "product_group": "DVD", "product_title": "Hercules in New York", "review_rating": 4, "product_category": "Action & Adventure", "product_sales_rank": 7621, "product_subcategory": "General", "similar_product_ids": ["B0000C3I6U", "B00018YC3M", "B00013RC8E", "B000063INF", "B0001Z37HM"], "review_helpful_votes": 14} -{"product_id": "B00005RFAI", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Missundaztood", "review_rating": 5, "product_category": "Dance & DJ", "product_sales_rank": 2800, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "B00005RGI0", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 242158, "product_subcategory": "General", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "B00005UW47", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "M!ssundaztood [German Bonus Track]", "review_rating": 5, "product_category": "Imports", "product_sales_rank": 112988, "product_subcategory": "Dance & DJ", "similar_product_ids": ["B00004RHZU", "B0000CAQ27", "B000066NW0", "B0000CAQ26", "B00006CXXU"], "review_helpful_votes": 0} -{"product_id": "B0000004QS", "customer_id": "A9JNFQOHDN0X0", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Conspiracy No. 5", "review_rating": 5, "product_category": "Christian & Gospel", "product_sales_rank": 26969, "product_subcategory": "Christian Rock", "similar_product_ids": ["B0000004QQ", "B00000JYAC", "B00005OKUS", "B0001Z36VO", "B00004TZBU"], "review_helpful_votes": 2} -{"product_id": "0968621414", "customer_id": "A9KF4UCP7DXLE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Indie Bible", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 692051, "product_subcategory": "Music", "similar_product_ids": [], "review_helpful_votes": 3} -{"product_id": "0968621422", "customer_id": "A9KF4UCP7DXLE", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "Book", "product_title": "The Indie Bible (Indie Bible)", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 492612, "product_subcategory": "Music", "similar_product_ids": [], "review_helpful_votes": 3} -{"product_id": "0671042262", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere ", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 122628, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} -{"product_id": "0684871270", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere ", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 223995, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} -{"product_id": "0743506405", "customer_id": "A9LAPV8XNKZVZ", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Book", "product_title": "The Blue Nowhere", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 781854, "product_subcategory": "Mystery", "similar_product_ids": ["0671038443", "0671026011", "0743437802", "0671024094", "0671024108"], "review_helpful_votes": 0} -{"product_id": "B0000025GR", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "Winner Takes All", "review_rating": 4, "product_category": "R&B", "product_sales_rank": 59367, "product_subcategory": "General", "similar_product_ids": ["B00000258G", "B00005NKKR", "B00005NKKS", "B0000025V4", "B000002LBT"], "review_helpful_votes": 2} -{"product_id": "B00005M9B6", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Body & Soul", "review_rating": 4, "product_category": "R&B", "product_sales_rank": 72965, "product_subcategory": "General", "similar_product_ids": ["B00004L8HV", "B00005V8T2", "B00005BC7O", "B000083MCY", "B00000BIL4"], "review_helpful_votes": 1} -{"product_id": "B00000BIL4", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Music", "product_title": "Body & Soul", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 12265, "product_subcategory": "General", "similar_product_ids": ["B00004L8HV", "B00005V8T2", "B00016XN8Y", "B00005BC7O", "B0000931MS"], "review_helpful_votes": 2} -{"product_id": "B000002AA9", "customer_id": "A9Q28YTLYREO7", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Best of Walter Jackson", "review_rating": 5, "product_category": "R&B", "product_sales_rank": 38822, "product_subcategory": "General", "similar_product_ids": ["B0000008JF", "B00003E435", "B00004SW64", "B00005K9SM", "B00000150B"], "review_helpful_votes": 5} -{"product_id": "B00005RIY5", "customer_id": "A9VU1SKTY5M09", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Queer as Folk - The Complete First Season (Showtime)", "review_rating": 4, "product_category": "Television", "product_sales_rank": 1961, "product_subcategory": "General", "similar_product_ids": ["B0000798EY", "B0000V46D6", "B0007DBJG4", "B0002MPQRS", "B0002I84JO"], "review_helpful_votes": 1} -{"product_id": "B00005RJ22", "customer_id": "A9VU1SKTY5M09", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Queer As Folk - The Complete First Season (Showtime)", "review_rating": 4, "product_category": "Television", "product_sales_rank": 6368, "product_subcategory": "General", "similar_product_ids": ["B0000798EY", "B0000V46D6", "B0007DBJG4", "B0002I84JO", "B0002MPQRS"], "review_helpful_votes": 1} -{"product_id": "0060952709", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 15, "product_group": "Book", "product_title": "3-Minute Abs", "review_rating": 2, "product_category": "Health, Mind & Body", "product_sales_rank": 22680, "product_subcategory": "Exercise & Fitness", "similar_product_ids": ["0060193395", "0812969472", "1579543081", "0972018417", "1579542921"], "review_helpful_votes": 2} -{"product_id": "0060193395", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 156, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} -{"product_id": "0694521485", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 72258, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} -{"product_id": "0694523194", "customer_id": "AA0GQZ1EATNFZ", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "Book", "product_title": "Body for Life", "review_rating": 3, "product_category": "Health, Mind & Body", "product_sales_rank": 89385, "product_subcategory": "Diets & Weight Loss", "similar_product_ids": ["0972018417", "0060515597", "1579546013", "0060952709", "1578260868"], "review_helpful_votes": 1} -{"product_id": "B00005B1ZW", "customer_id": "AA12M537YT203", "review_date": {"$date": 1013644800000}, "review_votes": 4, "product_group": "DVD", "product_title": "Harold Robbins' Body Parts", "review_rating": 4, "product_category": "Mystery & Suspense", "product_sales_rank": 35489, "product_subcategory": "Thrillers", "similar_product_ids": ["B00004YA1C", "B00009MEIH", "0780627792", "B00023P4I8", "B000059TP6"], "review_helpful_votes": 1} -{"product_id": "1573300780", "customer_id": "AA1G3JXDX6JQQ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "DVD", "product_title": "The Allman Brothers Band", "review_rating": 4, "product_category": "Music Video & Concerts", "product_sales_rank": 28164, "product_subcategory": "General", "similar_product_ids": ["B0000C7PWI", "B00008G83R", "6305130930", "B0002SPPSC", "6305019681"], "review_helpful_votes": 4} -{"product_id": "0965683621", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 61, "product_group": "Book", "product_title": "Race, Evolution, and Behavior ", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 401854, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 12} -{"product_id": "0965683605", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 62, "product_group": "Book", "product_title": "Race, Evolution, and Behavior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 146808, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 13} -{"product_id": "0965683613", "customer_id": "AA5LCMXB0KZ1J", "review_date": {"$date": 1013644800000}, "review_votes": 62, "product_group": "Book", "product_title": "Race, Evolution, and Behavior", "review_rating": 1, "product_category": "Nonfiction", "product_sales_rank": 121530, "product_subcategory": "Social Sciences", "similar_product_ids": ["0813340861", "081334008X", "0965638308", "0965638324", "0029146739"], "review_helpful_votes": 13} -{"product_id": "B00005RDSN", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Atlantis - The Lost Empire (Disney Collector's Edition)", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 12834, "product_subcategory": "Animation", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} -{"product_id": "B00005RDSQ", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 2377, "product_subcategory": "Animation", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} -{"product_id": "B00005RDVV", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 5875, "product_subcategory": "Adventure", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} -{"product_id": "B00005RDWG", "customer_id": "AA5XZVANDXGJE", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Video", "product_title": "Atlantis - The Lost Empire", "review_rating": 4, "product_category": "Kids & Family", "product_sales_rank": 19184, "product_subcategory": "Adventure", "similar_product_ids": ["B00005JLR2", "B000089G5O", "B00005AR3G", "B00005TN8K", "B00004R99J"], "review_helpful_votes": 1} -{"product_id": "B00005N9CV", "customer_id": "AA7DSULMWBHOW", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "The Look of Love", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 603, "product_subcategory": "General", "similar_product_ids": ["B00000J7S8", "B000148KK2", "B00006J9OT", "B000003NA4", "B000003N89"], "review_helpful_votes": 3} -{"product_id": "B00006L6YH", "customer_id": "AA7DSULMWBHOW", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Look of Love (Hybr) (Ms)", "review_rating": 5, "product_category": "Jazz", "product_sales_rank": 102740, "product_subcategory": "General", "similar_product_ids": ["B00000J7S8", "B000148KK2", "B00006J9OT", "B000003NA4", "B000003N89"], "review_helpful_votes": 3} -{"product_id": "0240516648", "customer_id": "AAFRDBLLQ3TZJ", "review_date": {"$date": 1013644800000}, "review_votes": 24, "product_group": "Book", "product_title": "Real-time 3D Character Animation with Visual C++ (Book & CD-ROM)", "review_rating": 5, "product_category": "Computers & Internet", "product_sales_rank": 68934, "product_subcategory": "Computer & Video Games", "similar_product_ids": ["1556229135", "1584502045", "0321228324", "1568811829", "1584502274"], "review_helpful_votes": 11} -{"product_id": "0316666009", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 7441, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} -{"product_id": "0446610038", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 3168, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} -{"product_id": "158621053X", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 395366, "product_subcategory": "Mystery", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446608815"], "review_helpful_votes": 7} -{"product_id": "1586210564", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die", "review_rating": 1, "product_category": "Books on Tape", "product_sales_rank": 155998, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} -{"product_id": "1586210572", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die (Women's Murder Club (Audio))", "review_rating": 1, "product_category": "Books on CD", "product_sales_rank": 363732, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} -{"product_id": "1586210599", "customer_id": "AAO89FWTAJ4ZI", "review_date": {"$date": 1013644800000}, "review_votes": 9, "product_group": "Book", "product_title": "1st to Die (Women's Murder Club (Audio))", "review_rating": 1, "product_category": "Books on CD", "product_sales_rank": 175694, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0446612790", "0316603570", "0446606189", "0446605484", "0446611212"], "review_helpful_votes": 7} -{"product_id": "B00004S2E9", "customer_id": "AAOTXJRW5HP94", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "Music", "product_title": "Essential Mix", "review_rating": 3, "product_category": "Dance & DJ", "product_sales_rank": 29813, "product_subcategory": "General", "similar_product_ids": ["B0001MLM1S", "B00005Q4PB", "B00000JG24", "B0006B2ACY", "B00009OKOQ"], "review_helpful_votes": 0} -{"product_id": "0130092290", "customer_id": "AAPBZ5T7COQBU", "review_date": {"$date": 1013644800000}, "review_votes": 68, "product_group": "Book", "product_title": "Core Servlets and JavaServer Pages, Vol. 1", "review_rating": 2, "product_category": "Computers & Internet", "product_sales_rank": 10577, "product_subcategory": "Web Development", "similar_product_ids": ["0130676144", "0131422464", "0131482025", "0596005725", "059600530X"], "review_helpful_votes": 63} -{"product_id": "0130893404", "customer_id": "AAPBZ5T7COQBU", "review_date": {"$date": 1013644800000}, "review_votes": 68, "product_group": "Book", "product_title": "Core Servlets and JavaServer Pages (JSP)", "review_rating": 2, "product_category": "Computers & Internet", "product_sales_rank": 63011, "product_subcategory": "Web Development", "similar_product_ids": ["0130676144", "0131422464", "0131482025", "0596005725", "059600530X"], "review_helpful_votes": 63} -{"product_id": "0968084206", "customer_id": "AAPYWOX2QGTYJ", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Book", "product_title": "Euchre", "review_rating": 4, "product_category": "Entertainment", "product_sales_rank": 359946, "product_subcategory": "Games", "similar_product_ids": [], "review_helpful_votes": 4} -{"product_id": "0553528947", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away From Heaven", "review_rating": 2, "product_category": "Books on Tape", "product_sales_rank": 300617, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} -{"product_id": "0553582755", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away from Heaven", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 18498, "product_subcategory": "Thrillers", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} -{"product_id": "0553801376", "customer_id": "AAT2O121DLFHR", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "One Door Away from Heaven", "review_rating": 2, "product_category": "Mystery & Thrillers", "product_sales_rank": 286350, "product_subcategory": "Thrillers", "similar_product_ids": ["0553582763", "0553582747", "0553584480", "0553580221", "0553802496"], "review_helpful_votes": 2} -{"product_id": "B000002V1I", "customer_id": "AAU5DBENOW7DM", "review_date": {"$date": 1013644800000}, "review_votes": 5, "product_group": "Music", "product_title": "Check Your Head", "review_rating": 5, "product_category": "Rap & Hip-Hop", "product_sales_rank": 4183, "product_subcategory": "East Coast", "similar_product_ids": ["B000002TP7", "B000002UUN", "B0000024JN", "B000007TE8", "B00021LRWM"], "review_helpful_votes": 5} -{"product_id": "1930928513", "customer_id": "AAUT2ZCRMTT8H", "review_date": {"$date": 1013644800000}, "review_votes": 51, "product_group": "Book", "product_title": "Turning the Page", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 199670, "product_subcategory": "General", "similar_product_ids": ["1932300155", "1931513988", "193151397X", "1931513767", "1560234695"], "review_helpful_votes": 44} -{"product_id": "0792841638", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "DVD", "product_title": "Hair", "review_rating": 5, "product_category": "Musicals & Performing Arts", "product_sales_rank": 1723, "product_subcategory": "General", "similar_product_ids": ["0783232071", "B00000K3TV", "0767827929", "B00000JYU8", "B000002W1S"], "review_helpful_votes": 0} -{"product_id": "B00004STCS", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 0, "product_group": "Video", "product_title": "Hair", "review_rating": 5, "product_category": "Musicals & Performing Arts", "product_sales_rank": 9708, "product_subcategory": "General", "similar_product_ids": ["0783232071", "B00000K3TV", "0767827929", "B00000JYU8", "B000002W1S"], "review_helpful_votes": 0} -{"product_id": "6302670306", "customer_id": "AAZ589RCSJ0E7", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "Video", "product_title": "Mindwalk", "review_rating": 5, "product_category": "Drama", "product_sales_rank": 1566, "product_subcategory": "General", "similar_product_ids": ["6305069743", "0553345729", "1570625190", "6302664845", "0385476760"], "review_helpful_votes": 6} -{"product_id": "0345361792", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 539, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} -{"product_id": "0345417976", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany (Ballantine Reader's Circle)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 26346, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} -{"product_id": "061303421X", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 494538, "product_subcategory": "Authors, A-Z", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} -{"product_id": "0679642595", "customer_id": "AB2AQMK9PCWWX", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Book", "product_title": "A Prayer for Owen Meany (Modern Library)", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 105174, "product_subcategory": "General", "similar_product_ids": ["034536676X", "0345387651", "0345424719", "034540047X", "B00006G3N5"], "review_helpful_votes": 0} -{"product_id": "B00005QXG9", "customer_id": "AB4QT2G99O7N0", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "C True Hollywood Stories", "review_rating": 1, "product_category": "Rap & Hip-Hop", "product_sales_rank": 110252, "product_subcategory": "East Coast", "similar_product_ids": ["B00009Y3PI", "B00000AFWY", "B00004UAOW", "B00007BH4Z", "B00027JYOE"], "review_helpful_votes": 0} -{"product_id": "1561709662", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Cards", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 803020, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "1576737330", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 4769, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "1576738108", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Gift Edition ", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 525856, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "1576738426", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez Audio", "review_rating": 1, "product_category": "Books on Tape", "product_sales_rank": 205151, "product_subcategory": "Literature & Fiction", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "1576738574", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez (Leather Edition)", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 351854, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "1576739074", "customer_id": "AB6TLT3LSHF45", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Prayer of Jabez (Breakthrough Series)", "review_rating": 1, "product_category": "Religion & Spirituality", "product_sales_rank": 110768, "product_subcategory": "Christianity", "similar_product_ids": ["1576739759", "1576739627", "1576739791", "159052201X", "1576738442"], "review_helpful_votes": 5} -{"product_id": "B00005NNOX", "customer_id": "AB8J6KKIATGL3", "review_date": {"$date": 1013644800000}, "review_votes": 2, "product_group": "Music", "product_title": "The Well", "review_rating": 5, "product_category": "Pop", "product_sales_rank": 25222, "product_subcategory": "Vocal Pop", "similar_product_ids": ["B000024QBF", "B00002487W", "B000024QBK", "B0001Z3TTI", "B000002VDZ"], "review_helpful_votes": 2} -{"product_id": "0449912639", "customer_id": "ABCNNP742AV30", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "Girls ", "review_rating": 1, "product_category": "Literature & Fiction", "product_sales_rank": 35862, "product_subcategory": "General", "similar_product_ids": ["0449006158", "0449907503", "039305103X", "0345443934", "0767903986"], "review_helpful_votes": 0} -{"product_id": "0743442792", "customer_id": "ABCNNP742AV30", "review_date": {"$date": 1013644800000}, "review_votes": 6, "product_group": "Book", "product_title": "The Honored Society", "review_rating": 1, "product_category": "Mystery & Thrillers", "product_sales_rank": 542152, "product_subcategory": "Thrillers", "similar_product_ids": ["0671900153", "0762418397"], "review_helpful_votes": 2} -{"product_id": "0060184906", "customer_id": "ABF5FMMZPOLAF", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "The Golems of Gotham ", "review_rating": 5, "product_category": "Literature & Fiction", "product_sales_rank": 641304, "product_subcategory": "General", "similar_product_ids": ["0312198655", "0312254180", "096795200X", "157322975X", "0618509283"], "review_helpful_votes": 4} -{"product_id": "B00008NRH0", "customer_id": "ABF5FMMZPOLAF", "review_date": {"$date": 1013644800000}, "review_votes": 11, "product_group": "Book", "product_title": "The Golems of Gotham", "review_rating": 5, "product_category": "", "product_sales_rank": 624527, "product_subcategory": "", "similar_product_ids": ["0312198655", "0312254180", "096795200X", "157322975X", "0618509283"], "review_helpful_votes": 4} -{"product_id": "630141277X", "customer_id": "ABFJYHVD8RHLE", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "Video", "product_title": "Working Girl", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 6883, "product_subcategory": "General", "similar_product_ids": ["B0000542C9", "B000059HAM", "B00000J123", "B00005S6K8", "6305696071"], "review_helpful_votes": 8} -{"product_id": "B000059HAK", "customer_id": "ABFJYHVD8RHLE", "review_date": {"$date": 1013644800000}, "review_votes": 10, "product_group": "DVD", "product_title": "Working Girl", "review_rating": 5, "product_category": "Comedy", "product_sales_rank": 3752, "product_subcategory": "General", "similar_product_ids": ["B0000542C9", "B000059HAM", "B00000J123", "B00005S6K8", "6305696071"], "review_helpful_votes": 8} -{"product_id": "B00005BJXA", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 1, "product_group": "DVD", "product_title": "The Giant Gila Monster/The Wasp Woman", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 23747, "product_subcategory": "General", "similar_product_ids": [], "review_helpful_votes": 1} -{"product_id": "B00004W190", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 3, "product_group": "DVD", "product_title": "Bad Girls Go To Hell/Another Day Another Man", "review_rating": 5, "product_category": "Classics", "product_sales_rank": 40553, "product_subcategory": "General", "similar_product_ids": ["B000056NW6", "B0002IQB8U", "B00022PYRU", "B0002NRRQ0", "B0002W4TL2"], "review_helpful_votes": 2} -{"product_id": "B00005ALM0", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "The Violent Years/Girl Gang", "review_rating": 5, "product_category": "Action & Adventure", "product_sales_rank": 15399, "product_subcategory": "General", "similar_product_ids": ["B00005ALLZ", "B0002235LM", "B00005LP6F", "B0002NRRT2", "B0000CG8H0"], "review_helpful_votes": 6} -{"product_id": "B00005B6KQ", "customer_id": "ABH4G7TVI6G2T", "review_date": {"$date": 1013644800000}, "review_votes": 8, "product_group": "DVD", "product_title": "The Notorious Daughter of Fanny Hill / The Head Mistress", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 20963, "product_subcategory": "General", "similar_product_ids": ["B0002W4TL2", "B00005MM5O", "B0002NRRQ0", "B0002EJ7JE", "B00005R1NR"], "review_helpful_votes": 7} -{"product_id": "B00005B6KQ", "customer_id": null, "review_date": {"$date": 1013644800000}, "review_votes": true, "product_group": false, "product_title": "The Notorious Daughter of Fanny Hill / The Head Mistress", "review_rating": 5, "product_category": "Science Fiction & Fantasy", "product_sales_rank": 20963, "product_subcategory": "General", "similar_product_ids": ["B0002W4TL2", "B00005MM5O", "B0002NRRQ0", "B0002EJ7JE", "B00005R1NR"], "review_helpful_votes": 7} -{"array": [1,2,3]} -{"array": [2,3,4]} -{"array": [3,4,5]} -{"array": [2,3]} -{"array": [2]} -{"array": [4,5]} -{"t": 1} -{"t": 99} -{"t": {}} -{"t": {"y": "z"}} -{"t": []} -{"t": [1]} -{"t": "x"} -{"t": "a"} -{"t": true} -{"t": false} -[1, 2, 3] -["a", "b", "c"] -1 -2 -3 -4 -5 -null -null -null -false -false -true -"aaa" -"bbb" -"ccc" -"ddd" \ No newline at end of file diff --git a/jsquery/expected/jsquery.out b/jsquery/expected/jsquery.out deleted file mode 100644 index e747d9a3f5..0000000000 --- a/jsquery/expected/jsquery.out +++ /dev/null @@ -1,2923 +0,0 @@ -CREATE EXTENSION jsquery; -set escape_string_warning=off; -set standard_conforming_strings=on; -CREATE TABLE test_jsquery (v jsonb); -\copy test_jsquery from 'data/test_jsquery.data' -select 'asd.zzz = 13'::jsquery; - jsquery ------------------- - "asd"."zzz" = 13 -(1 row) - -select 'asd.zzz < 13'::jsquery; - jsquery ------------------- - "asd"."zzz" < 13 -(1 row) - -select 'asd(zzz < 13)'::jsquery; - jsquery ------------------- - "asd"."zzz" < 13 -(1 row) - -select 'asd(zzz < 13 AND x = true)'::jsquery; - jsquery ----------------------------------- - "asd"("zzz" < 13 AND "x" = true) -(1 row) - -select 'asd(zzz < 13 AND x = "true")'::jsquery; - jsquery ------------------------------------- - "asd"("zzz" < 13 AND "x" = "true") -(1 row) - -select 'asd(zzz < 13 AND x.zxc = "true")'::jsquery; - jsquery ------------------------------------------- - "asd"("zzz" < 13 AND "x"."zxc" = "true") -(1 row) - -select 'asd(zzz < 13 OR #.zxc = "true" /* test */)'::jsquery; - jsquery ---------------------------------------- - "asd"("zzz" < 13 OR #."zxc" = "true") -(1 row) - -select 'asd(* < 13 AND /* ttt */ #.zxc = "true")'::jsquery; - jsquery ------------------------------------- - "asd"(* < 13 AND #."zxc" = "true") -(1 row) - -select '(* < 13 AND #.zxc = "true")'::jsquery; - jsquery -------------------------------- - (* < 13 AND #."zxc" = "true") -(1 row) - -select '* < 13 AND #.zxc/* t2 */ = "true"'::jsquery; - jsquery -------------------------------- - (* < 13 AND #."zxc" = "true") -(1 row) - -select '* < 13 AND #.zxc"x" = "true"'::jsquery; -ERROR: bad jsquery representation -LINE 1: select '* < 13 AND #.zxc"x" = "true"'::jsquery; - ^ -DETAIL: syntax error, unexpected STRING_P at or near """ -select 'a < 1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < -1'::jsquery; - jsquery ----------- - "a" < -1 -(1 row) - -select 'a < +1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < .1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < -.1'::jsquery; - jsquery ------------- - "a" < -0.1 -(1 row) - -select 'a < +.1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < 0.1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < -0.1'::jsquery; - jsquery ------------- - "a" < -0.1 -(1 row) - -select 'a < +0.1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < 10.1'::jsquery; - jsquery ------------- - "a" < 10.1 -(1 row) - -select 'a < -10.1'::jsquery; - jsquery -------------- - "a" < -10.1 -(1 row) - -select 'a < +10.1'::jsquery; - jsquery ------------- - "a" < 10.1 -(1 row) - -select 'a < 1e1'::jsquery; - jsquery ----------- - "a" < 10 -(1 row) - -select 'a < -1e1'::jsquery; - jsquery ------------ - "a" < -10 -(1 row) - -select 'a < +1e1'::jsquery; - jsquery ----------- - "a" < 10 -(1 row) - -select 'a < .1e1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < -.1e1'::jsquery; - jsquery ----------- - "a" < -1 -(1 row) - -select 'a < +.1e1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < 0.1e1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < -0.1e1'::jsquery; - jsquery ----------- - "a" < -1 -(1 row) - -select 'a < +0.1e1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < 10.1e1'::jsquery; - jsquery ------------ - "a" < 101 -(1 row) - -select 'a < -10.1e1'::jsquery; - jsquery ------------- - "a" < -101 -(1 row) - -select 'a < +10.1e1'::jsquery; - jsquery ------------ - "a" < 101 -(1 row) - -select 'a < 1e-1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < -1e-1'::jsquery; - jsquery ------------- - "a" < -0.1 -(1 row) - -select 'a < +1e-1'::jsquery; - jsquery ------------ - "a" < 0.1 -(1 row) - -select 'a < .1e-1'::jsquery; - jsquery ------------- - "a" < 0.01 -(1 row) - -select 'a < -.1e-1'::jsquery; - jsquery -------------- - "a" < -0.01 -(1 row) - -select 'a < +.1e-1'::jsquery; - jsquery ------------- - "a" < 0.01 -(1 row) - -select 'a < 0.1e-1'::jsquery; - jsquery ------------- - "a" < 0.01 -(1 row) - -select 'a < -0.1e-1'::jsquery; - jsquery -------------- - "a" < -0.01 -(1 row) - -select 'a < +0.1e-1'::jsquery; - jsquery ------------- - "a" < 0.01 -(1 row) - -select 'a < 10.1e-1'::jsquery; - jsquery ------------- - "a" < 1.01 -(1 row) - -select 'a < -10.1e-1'::jsquery; - jsquery -------------- - "a" < -1.01 -(1 row) - -select 'a < +10.1e-1'::jsquery; - jsquery ------------- - "a" < 1.01 -(1 row) - -select 'a < 1e+1'::jsquery; - jsquery ----------- - "a" < 10 -(1 row) - -select 'a < -1e+1'::jsquery; - jsquery ------------ - "a" < -10 -(1 row) - -select 'a < +1e+1'::jsquery; - jsquery ----------- - "a" < 10 -(1 row) - -select 'a < .1e+1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < -.1e+1'::jsquery; - jsquery ----------- - "a" < -1 -(1 row) - -select 'a < +.1e+1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < 0.1e+1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < -0.1e+1'::jsquery; - jsquery ----------- - "a" < -1 -(1 row) - -select 'a < +0.1e+1'::jsquery; - jsquery ---------- - "a" < 1 -(1 row) - -select 'a < 10.1e+1'::jsquery; - jsquery ------------ - "a" < 101 -(1 row) - -select 'a < -10.1e+1'::jsquery; - jsquery ------------- - "a" < -101 -(1 row) - -select 'a < +10.1e+1'::jsquery; - jsquery ------------ - "a" < 101 -(1 row) - -select 'a in (0,1,2)'::jsquery; - jsquery ------------------- - "a" IN (0, 1, 2) -(1 row) - -select 'a IN (0,null, "null", xxx, "zzz", 2)'::jsquery; - jsquery -------------------------------------------- - "a" IN (0, null, "null", "xxx", "zzz", 2) -(1 row) - -select 'not < 1'::jsquery; - jsquery ------------ - "not" < 1 -(1 row) - -select 'not not < 1'::jsquery; - jsquery ------------------ - (NOT "not" < 1) -(1 row) - -select 'not( not < 1)'::jsquery; - jsquery ------------------ - (NOT "not" < 1) -(1 row) - -select 'not.x < 1'::jsquery; - jsquery ---------------- - "not"."x" < 1 -(1 row) - -select 'x.not < 1'::jsquery; - jsquery ---------------- - "x"."not" < 1 -(1 row) - -select 'a.%(not x > 0 and not (y < 0 or z = 0))'::jsquery; - jsquery ------------------------------------------------------ - "a".%((NOT "x" > 0) AND (NOT ("y" < 0 OR "z" = 0))) -(1 row) - -select 'is < 1'::jsquery; - jsquery ----------- - "is" < 1 -(1 row) - -select 'in < 1'::jsquery; - jsquery ----------- - "in" < 1 -(1 row) - -select 'not is < 1'::jsquery; - jsquery ----------------- - (NOT "is" < 1) -(1 row) - -select 'not in < 1'::jsquery; - jsquery ----------------- - (NOT "in" < 1) -(1 row) - -select 'in in (1,2)'::jsquery; - jsquery ----------------- - "in" IN (1, 2) -(1 row) - -select 'is in (1,2)'::jsquery; - jsquery ----------------- - "is" IN (1, 2) -(1 row) - -select 'not in (1,2)'::jsquery; - jsquery ------------------ - "not" IN (1, 2) -(1 row) - -select 'in is numeric'::jsquery; - jsquery ------------------ - "in" IS NUMERIC -(1 row) - -select 'is is numeric'::jsquery; - jsquery ------------------ - "is" IS NUMERIC -(1 row) - -select 'not is numeric'::jsquery; - jsquery ------------------- - "not" IS NUMERIC -(1 row) - -select 'not.in < 1'::jsquery; - jsquery ----------------- - "not"."in" < 1 -(1 row) - -select 'not.is < 1'::jsquery; - jsquery ----------------- - "not"."is" < 1 -(1 row) - -select 'not.not < 1'::jsquery; - jsquery ------------------ - "not"."not" < 1 -(1 row) - -select 'in.in < 1'::jsquery; - jsquery ---------------- - "in"."in" < 1 -(1 row) - -select 'in.is < 1'::jsquery; - jsquery ---------------- - "in"."is" < 1 -(1 row) - -select 'in.not < 1'::jsquery; - jsquery ----------------- - "in"."not" < 1 -(1 row) - -select 'is.in < 1'::jsquery; - jsquery ---------------- - "is"."in" < 1 -(1 row) - -select 'is.is < 1'::jsquery; - jsquery ---------------- - "is"."is" < 1 -(1 row) - -select 'is.not < 1'::jsquery; - jsquery ----------------- - "is"."not" < 1 -(1 row) - -select 'a.b.#4 > 4'::jsquery; - jsquery ----------------- - "a"."b".#4 > 4 -(1 row) - -select 'a.b.#10203.* > 4'::jsquery; - jsquery ----------------------- - "a"."b".#10203.* > 4 -(1 row) - -select '{"a": {"b": null}}'::jsonb @@ 'a.b = 1'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": null}}'::jsonb @@ 'a.b = null'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": null}}'::jsonb @@ 'a.b = false'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": false}}'::jsonb @@ 'a.b = false'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": false}}'::jsonb @@ 'a.b = true'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": true}}'::jsonb @@ 'a.b = true'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 1'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 1'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 1'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 1'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 1'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 2'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 2'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 0'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 0'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 0'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 1 ]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1 ]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1 ]'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1,2,3,4 ]'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1,2,3,4 ]'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 4'; - ?column? ----------- - f -(1 row) - -select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 3'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a = 4'; - ?column? ----------- - f -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a = 4'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 1 OR a=3)'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 OR a=1)'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=1)'; - ?column? ----------- - f -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=2)' as "false"; - false -------- - f -(1 row) - -select '[{"a": 2, "b":3}, {"a": 3, "b": 1}]'::jsonb @@ '#(b = 1 and a=3)'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a.a = 4'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a.a = 4'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.#.a.a = 4'; - ?column? ----------- - t -(1 row) - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.*.a.a = 4'; - ?column? ----------- - t -(1 row) - -select '{"a": 1}'::jsonb @@ 'a in (0,1,2)'; - ?column? ----------- - t -(1 row) - -select '{"a": 1}'::jsonb @@ 'a in (0,2)'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#=2'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 5 ]'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a=*'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b=*'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.c=*'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b = [1,2,3]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# = [1,2,3]'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b && [1,2,3]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# && [1,2,3]'; - ?column? ----------- - f -(1 row) - -select 'asd.# = 3'::jsquery & 'zzz = true' | 'xxx.# = zero'; - ?column? ------------------------------------------------------- - (("asd".# = 3 AND "zzz" = true) OR "xxx".# = "zero") -(1 row) - -select !'asd.# = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; - ?column? ------------------------------------------------------------------- - (((NOT "asd".# = 3) AND "zzz" = true) OR (NOT "xxx".# = "zero")) -(1 row) - -select !'asd.#3.f = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; - ?column? ------------------------------------------------------------------------ - (((NOT "asd".#3."f" = 3) AND "zzz" = true) OR (NOT "xxx".# = "zero")) -(1 row) - -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0]'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,1]'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,3]'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 2 ]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b($ && [ 2 ])'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b && [ 2 ]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b ($ && [ 2 ])'; - ?column? ----------- - t -(1 row) - -select '[1,2,3]'::jsonb @@ '# && [2]'; - ?column? ----------- - f -(1 row) - -select '[1,2,3]'::jsonb @@ '#($ && [2])'; - ?column? ----------- - f -(1 row) - -select '[1,2,3]'::jsonb @@ '$ && [2]'; - ?column? ----------- - t -(1 row) - -select '[1,2,3]'::jsonb @@ '$ ($ && [2])'; - ?column? ----------- - t -(1 row) - -select '[1,2,3]'::jsonb @@ '$ = 2'; - ?column? ----------- - f -(1 row) - -select '[1,2,3]'::jsonb @@ '# = 2'; - ?column? ----------- - t -(1 row) - -select '[1,2,3]'::jsonb @@ '#.$ = 2'; - ?column? ----------- - t -(1 row) - -select '[1,2,3]'::jsonb @@ '#($ = 2)'; - ?column? ----------- - t -(1 row) - -select '[3,4]'::jsonb @@ '#($ > 2 and $ < 5)'; - ?column? ----------- - t -(1 row) - -select '[3,4]'::jsonb @@ '# > 2 and # < 5'; - ?column? ----------- - t -(1 row) - -select '[1,6]'::jsonb @@ '#($ > 2 and $ < 5)'; - ?column? ----------- - f -(1 row) - -select '[1,6]'::jsonb @@ '# > 2 and # < 5'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.b=3'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ 'a.%=3'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.%="hey"'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%="hey"'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%=[5,6]'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#1 = 2'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#2 = 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#3 = 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#1.x = 2'; - ?column? ----------- - t -(1 row) - -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#2.x = 2'; - ?column? ----------- - f -(1 row) - -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#3.x = 2'; - ?column? ----------- - f -(1 row) - -select '"XXX"'::jsonb @@ '$="XXX"'; - ?column? ----------- - t -(1 row) - -select '"XXX"'::jsonb @@ '#.$="XXX"'; - ?column? ----------- - f -(1 row) - ---Unicode -select 'a\t = "dollar \u0024 character"'::jsquery; - jsquery ------------------------------- - "a\t" = "dollar $ character" -(1 row) - -select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar \u0024 character"'; - ?column? ----------- - t -(1 row) - -select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar $ character"'; - ?column? ----------- - t -(1 row) - -select '{ "a": "dollar $ character" }'::jsonb @@ '* = "dollar \u0024 character"'; - ?column? ----------- - t -(1 row) - -select 'a\r = "\n\""'::jsquery; - jsquery ----------------- - "a\r" = "\n\"" -(1 row) - -select 'a\r = "\u0000"'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = "\u0000"'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = \u0000'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = \u0000'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = "\abcd"'::jsquery AS err; -ERROR: bad jsquery representation -LINE 1: select 'a\r = "\abcd"'::jsquery AS err; - ^ -DETAIL: Escape sequence is invalid at or near "\a" -select 'a\r = "\\abcd"'::jsquery; - jsquery ------------------- - "a\r" = "\\abcd" -(1 row) - -select 'a\r = "x\u0000"'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = "x\u0000"'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = x\u0000'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = x\u0000'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = "x\abcd"'::jsquery AS err; -ERROR: bad jsquery representation -LINE 1: select 'a\r = "x\abcd"'::jsquery AS err; - ^ -DETAIL: Escape sequence is invalid at or near "\a" -select 'a\r = "x\\abcd"'::jsquery; - jsquery -------------------- - "a\r" = "x\\abcd" -(1 row) - -select 'a\r = "x\u0000x"'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = "x\u0000x"'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = x\u0000x'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = x\u0000x'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = "x\abcdx"'::jsquery AS err; -ERROR: bad jsquery representation -LINE 1: select 'a\r = "x\abcdx"'::jsquery AS err; - ^ -DETAIL: Escape sequence is invalid at or near "\a" -select 'a\r = "x\\abcdx"'::jsquery; - jsquery --------------------- - "a\r" = "x\\abcdx" -(1 row) - -select 'a\r = "\u0000x"'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = "\u0000x"'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = \u0000x'::jsquery; -ERROR: unsupported Unicode escape sequence -LINE 1: select 'a\r = \u0000x'::jsquery; - ^ -DETAIL: \u0000 cannot be converted to text. -select 'a\r = "\abcdx"'::jsquery AS err; -ERROR: bad jsquery representation -LINE 1: select 'a\r = "\abcdx"'::jsquery AS err; - ^ -DETAIL: Escape sequence is invalid at or near "\a" -select 'a\r = "\\abcdx"'::jsquery; - jsquery -------------------- - "a\r" = "\\abcdx" -(1 row) - -select 'a\r = x"\\abcd"'::jsquery AS err; -ERROR: bad jsquery representation -LINE 1: select 'a\r = x"\\abcd"'::jsquery AS err; - ^ -DETAIL: syntax error, unexpected STRING_P, expecting $end at or near """ ---IS -select 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric OR as is string'::jsquery; - jsquery -------------------------------------------------------------------------------------------------- - (((("as" IS BOOLEAN OR "as" IS ARRAY) OR "as" IS OBJECT) OR "as" IS NUMERIC) OR "as" IS STRING) -(1 row) - -select '{"as": "xxx"}' @@ 'as IS string'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"as": "xxx"}' @@ 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"as": 5}' @@ 'as is Numeric'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"as": true}' @@ 'as is boolean'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"as": false}' @@ 'as is boolean'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"as": "false"}' @@ 'as is boolean'::jsquery; - ?column? ----------- - f -(1 row) - -select '["xxx"]' @@ '$ IS array'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"as": false}' @@ '$ IS object'::jsquery; - ?column? ----------- - t -(1 row) - -select '"xxx"' @@ '$ IS string'::jsquery; - ?column? ----------- - t -(1 row) - -select '"xxx"' @@ '$ IS numeric'::jsquery; - ?column? ----------- - f -(1 row) - ---hint -select 'a /*-- noindex */ = 5'::jsquery; - jsquery --------------------------- - "a" /*-- noindex */ = 5 -(1 row) - -select 'a /*-- index */ = 5'::jsquery; - jsquery ------------------------- - "a" /*-- index */ = 5 -(1 row) - -select 'asd.# = 3'::jsquery & 'zzz /*-- noindex */ = true' | 'xxx.# /*-- index */ = zero'; - ?column? --------------------------------------------------------------------------------------- - (("asd".# = 3 AND "zzz" /*-- noindex */ = true) OR "xxx".# /*-- index */ = "zero") -(1 row) - -select 'a /*-- xxx */ = 5'::jsquery; - jsquery ---------- - "a" = 5 -(1 row) - -select 'a /* index */ = 5'::jsquery; - jsquery ---------- - "a" = 5 -(1 row) - -select 'a /* noindex */ = 5'::jsquery; - jsquery ---------- - "a" = 5 -(1 row) - -select 'a = /*-- noindex */ 5'::jsquery; -ERROR: bad jsquery representation -LINE 1: select 'a = /*-- noindex */ 5'::jsquery; - ^ -DETAIL: syntax error, unexpected HINT_P at or near "*/" -select 'a = /* noindex */ 5'::jsquery; - jsquery ---------- - "a" = 5 -(1 row) - ---LENGTH -select 'a.@# = 4'::jsquery; - jsquery ------------- - "a".@# = 4 -(1 row) - -select 'a.@#.$ = 4'::jsquery as noerror; - noerror --------------- - "a".@#.$ = 4 -(1 row) - -select 'a.@#.a = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.a = 4'::jsquery as error; - ^ -select 'a.@#.* = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.* = 4'::jsquery as error; - ^ -select 'a.@#.% = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.% = 4'::jsquery as error; - ^ -select 'a.@#.# = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.# = 4'::jsquery as error; - ^ -select 'a.@#.*: = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.*: = 4'::jsquery as error; - ^ -select 'a.@#.%: = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.%: = 4'::jsquery as error; - ^ -select 'a.@#.#: = 4'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@#.#: = 4'::jsquery as error; - ^ -select 'a.@# (a = 5 or b = 6)'::jsquery as error; -ERROR: Array length should be last in path -LINE 1: select 'a.@# (a = 5 or b = 6)'::jsquery as error; - ^ -select '[]' @@ '@# = 0'::jsquery; - ?column? ----------- - t -(1 row) - -select '[]' @@ '@# < 2'::jsquery; - ?column? ----------- - t -(1 row) - -select '[]' @@ '@# > 1'::jsquery; - ?column? ----------- - f -(1 row) - -select '[1]' @@ '@# = 0'::jsquery; - ?column? ----------- - f -(1 row) - -select '[1]' @@ '@# < 2'::jsquery; - ?column? ----------- - t -(1 row) - -select '[1]' @@ '@# > 1'::jsquery; - ?column? ----------- - f -(1 row) - -select '[1,2]' @@ '@# = 0'::jsquery; - ?column? ----------- - f -(1 row) - -select '[1,2]' @@ '@# < 2'::jsquery; - ?column? ----------- - f -(1 row) - -select '[1,2]' @@ '@# > 1'::jsquery; - ?column? ----------- - t -(1 row) - -select '[1,2]' @@ '@# in (1, 2)'::jsquery; - ?column? ----------- - t -(1 row) - -select '[1,2]' @@ '@# in (1, 3)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":[1,2]}' @@ '@# in (2, 4)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":[1,2]}' @@ 'a.@# in (2, 4)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":[1,2]}' @@ '@# = 1'::jsquery; - ?column? ----------- - t -(1 row) - ---ALL -select 'a.*: = 4'::jsquery; - jsquery ------------- - "a".*: = 4 -(1 row) - -select '%: = 4'::jsquery; - jsquery ---------- - %: = 4 -(1 row) - -select '#:.i = 4'::jsquery; - jsquery ------------- - #:."i" = 4 -(1 row) - -select '[]' @@ '#: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '[2,3,4]' @@ '#: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '[2,3,5]' @@ '#: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '[2,3,5]' @@ '# ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '[2,3,"x"]' @@ '#: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{}' @@ '%: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{}' @@ '*: ($ is object)'::jsquery; - ?column? ----------- - t -(1 row) - -select '"a"' @@ '*: is string'::jsquery; - ?column? ----------- - t -(1 row) - -select '1' @@ '*: is string'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":2,"b":3,"c":4}' @@ '%: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":2,"b":3,"c":5}' @@ '%: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":2,"b":3,"c":5}' @@ '% ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":2,"b":3,"c":"x"}' @@ '%: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":2,"b":3,"c":4}' @@ '*: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":2,"b":3,"c":5}' @@ '*: ($ > 1 and $ < 5)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":2,"b":3,"c":4}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":2,"b":3,"c":5}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 1 and $ < 5))'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 0 and $ < 5))'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 0 and $ < 5))'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '* ($ > 0 and $ < 5)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR $ is numeric)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is numeric)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":8}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":"x"}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":null}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '%:.aa is numeric'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1}, "b":{"aa":true, "bb":2}}' @@ '%:.aa is numeric'::jsquery; - ?column? ----------- - f -(1 row) - -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}, "aa":16}' @@ '*: (not $ is object or $.aa is numeric)'::jsquery; - ?column? ----------- - t -(1 row) - -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '*: (not $ is object or $.aa is numeric or % is object)'::jsquery; - ?column? ----------- - t -(1 row) - -SELECT 'test.# IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)'::jsquery; - jsquery ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - "test".# IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64) -(1 row) - -select '[]' @@ '(@# > 0 and #: = 16)'::jsquery; - ?column? ----------- - f -(1 row) - -select '[16]' @@ '(@# > 0 and #: = 16)'::jsquery; - ?column? ----------- - t -(1 row) - ---extract entries for index scan -SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); - gin_debug_query_path_value ----------------------------- - AND + - z = 5 , entry 0 + - OR + - x.y.a = 1 , entry 1 + - x.y.b = 2 , entry 2 + - -(1 row) - -SELECT gin_debug_query_path_value('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('#(x = "a" and y > 0 and y < 1 and z > 0)'); - gin_debug_query_path_value ----------------------------- - #.x = "a" , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); - gin_debug_query_path_value ------------------------------ - AND + - #.x = "a" , entry 0 + - #.y >= 0 , < 1 , entry 1 + - -(1 row) - -SELECT gin_debug_query_path_value('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); - gin_debug_query_path_value ------------------------------ - AND + - #.y > 0 , <= 1 , entry 0 + - #.z > 0 , entry 1 + - -(1 row) - -SELECT gin_debug_query_path_value('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); - gin_debug_query_path_value ----------------------------- - AND + - x = 1 , entry 0 + - OR + - y > 0 , < 1 , entry 1 + - z > 0 , entry 2 + - -(1 row) - -SELECT gin_debug_query_path_value('%.x = 1'); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('*.x = "b"'); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('x && [1,2,3]'); - gin_debug_query_path_value ----------------------------- - OR + - x.# = 1 , entry 0 + - x.# = 2 , entry 1 + - x.# = 3 , entry 2 + - -(1 row) - -SELECT gin_debug_query_path_value('x @> [1,2,3]'); - gin_debug_query_path_value ----------------------------- - AND + - x.# = 1 , entry 0 + - x.# = 2 , entry 1 + - x.# = 3 , entry 2 + - -(1 row) - -SELECT gin_debug_query_path_value('x <@ [1,2,3]'); - gin_debug_query_path_value ----------------------------- - OR + - x = [] , entry 0 + - x.# = 1 , entry 1 + - x.# = 2 , entry 2 + - x.# = 3 , entry 3 + - -(1 row) - -SELECT gin_debug_query_path_value('x = *'); - gin_debug_query_path_value ----------------------------- - x = * , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('x is boolean'); - gin_debug_query_path_value ----------------------------- - x IS boolean , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('x is string'); - gin_debug_query_path_value ----------------------------- - x IS string , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('x is numeric'); - gin_debug_query_path_value ----------------------------- - x IS numeric , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('x is array'); - gin_debug_query_path_value ----------------------------- - x IS array , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('x is object'); - gin_debug_query_path_value ----------------------------- - x IS object , entry 0 + - -(1 row) - -SELECT gin_debug_query_path_value('#:(x=1) AND %:(y=1) AND *:(z=1)'); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); - gin_debug_query_path_value ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_path_value('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); - gin_debug_query_path_value ----------------------------- - #.x = 1 , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); - gin_debug_query_value_path ----------------------------- - AND + - z = 5 , entry 0 + - OR + - x.y.a = 1 , entry 1 + - x.y.b = 2 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('#(x = "a" and y > 0 and y < 1 and z > 0)'); - gin_debug_query_value_path ----------------------------- - #.x = "a" , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); - gin_debug_query_value_path ------------------------------ - AND + - #.x = "a" , entry 0 + - #.y >= 0 , < 1 , entry 1 + - -(1 row) - -SELECT gin_debug_query_value_path('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); - gin_debug_query_value_path ------------------------------ - AND + - #.y > 0 , <= 1 , entry 0 + - #.z > 0 , entry 1 + - -(1 row) - -SELECT gin_debug_query_value_path('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); - gin_debug_query_value_path ----------------------------- - AND + - x = 1 , entry 0 + - OR + - y > 0 , < 1 , entry 1 + - z > 0 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('%.x = 1'); - gin_debug_query_value_path ----------------------------- - %.x = 1 , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('*.x = "b"'); - gin_debug_query_value_path ----------------------------- - *.x = "b" , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x && [1,2,3]'); - gin_debug_query_value_path ----------------------------- - OR + - x.# = 1 , entry 0 + - x.# = 2 , entry 1 + - x.# = 3 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('x @> [1,2,3]'); - gin_debug_query_value_path ----------------------------- - AND + - x.# = 1 , entry 0 + - x.# = 2 , entry 1 + - x.# = 3 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('x <@ [1,2,3]'); - gin_debug_query_value_path ----------------------------- - OR + - x = [] , entry 0 + - x.# = 1 , entry 1 + - x.# = 2 , entry 2 + - x.# = 3 , entry 3 + - -(1 row) - -SELECT gin_debug_query_value_path('x = [1,2,3]'); - gin_debug_query_value_path ----------------------------- - AND + - x.# = 1 , entry 0 + - x.# = 2 , entry 1 + - x.# = 3 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('x = *'); - gin_debug_query_value_path ----------------------------- - x = * , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x is boolean'); - gin_debug_query_value_path ----------------------------- - x IS boolean , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x is string'); - gin_debug_query_value_path ----------------------------- - x IS string , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x is numeric'); - gin_debug_query_value_path ----------------------------- - x IS numeric , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x is array'); - gin_debug_query_value_path ----------------------------- - x IS array , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('x is object'); - gin_debug_query_value_path ----------------------------- - x IS object , entry 0 + - -(1 row) - -SELECT gin_debug_query_value_path('#:(x=1) AND %:(y=1) AND *:(z=1)'); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); - gin_debug_query_value_path ----------------------------- - AND + - #.x = 1 , entry 0 + - %.y = 1 , entry 1 + - *.z = 1 , entry 2 + - -(1 row) - -SELECT gin_debug_query_value_path('(@# > 0 and #: = 16)'); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - -SELECT gin_debug_query_value_path('*.@# ($ = 4 or $ = 2)'); - gin_debug_query_value_path ----------------------------- - NULL + - -(1 row) - ----table and index -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0; - count -------- - 654 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 19; - count -------- - 13 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 < 19; - count -------- - 985 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 >= 19; - count -------- - 16 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 <= 19; - count -------- - 988 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 = 19; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 16 AND - (v->>'review_helpful_votes')::int4 < 20; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - count -------- - 654 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; - count -------- - 13 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; - count -------- - 985 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; - count -------- - 16 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; - count -------- - 988 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; - count -------- - 54 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'customer_id = null'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_votes = true'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'product_group = false'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 't = *'; - count -------- - 10 -(1 row) - -select count(*) from test_jsquery where v @@ 't is boolean'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is string'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is numeric'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is object'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is boolean'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is string'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is numeric'; - count -------- - 5 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is object'; - count -------- - 1017 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; - count -------- - 51 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; - count -------- - 1001 -(1 row) - -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; - count -------- - 40 -(1 row) - -select count(*) from test_jsquery where v @@ '$ > 2'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ = false'; - count -------- - 2 -(1 row) - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; - v -------------------- - {"array": [2]} - {"array": [2, 3]} -(2 rows) - -select v from test_jsquery where v @@ 'array && [2,3]' order by v; - v ----------------------- - {"array": [2]} - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} - {"array": [3, 4, 5]} -(5 rows) - -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; - v ----------------------- - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} -(3 rows) - -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - v -------------------- - {"array": [2, 3]} -(1 row) - -create index t_idx on test_jsquery using gin (v jsonb_value_path_ops); -set enable_seqscan = off; -explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - QUERY PLAN ------------------------------------------------------------------------- - Aggregate - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) -(5 rows) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - count -------- - 654 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; - count -------- - 13 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; - count -------- - 985 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; - count -------- - 16 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; - count -------- - 988 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; - count -------- - 54 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'customer_id = null'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_votes = true'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'product_group = false'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 't = *'; - count -------- - 10 -(1 row) - -select count(*) from test_jsquery where v @@ 't is boolean'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is string'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is numeric'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is object'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is boolean'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is string'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is numeric'; - count -------- - 5 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is object'; - count -------- - 1017 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; - count -------- - 51 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; - count -------- - 1001 -(1 row) - -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ '$ > 2'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ = false'; - count -------- - 2 -(1 row) - -explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" <@ [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" <@ [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" && [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" && [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" @> [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" @> [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; - QUERY PLAN --------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" = [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" = [2, 3]'::jsquery) -(6 rows) - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; - v -------------------- - {"array": [2]} - {"array": [2, 3]} -(2 rows) - -select v from test_jsquery where v @@ 'array && [2,3]' order by v; - v ----------------------- - {"array": [2]} - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} - {"array": [3, 4, 5]} -(5 rows) - -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; - v ----------------------- - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} -(3 rows) - -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - v -------------------- - {"array": [2, 3]} -(1 row) - -drop index t_idx; -create index t_idx on test_jsquery using gin (v jsonb_path_value_ops); -set enable_seqscan = off; -explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - QUERY PLAN ------------------------------------------------------------------------- - Aggregate - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"review_helpful_votes" > 0'::jsquery) -(5 rows) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - count -------- - 654 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; - count -------- - 13 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; - count -------- - 985 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; - count -------- - 16 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; - count -------- - 988 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; - count -------- - 8 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; - count -------- - 54 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ 'customer_id = null'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'review_votes = true'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 'product_group = false'; - count -------- - 1 -(1 row) - -select count(*) from test_jsquery where v @@ 't = *'; - count -------- - 10 -(1 row) - -select count(*) from test_jsquery where v @@ 't is boolean'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is string'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is numeric'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ 't is object'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is boolean'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is string'; - count -------- - 4 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is numeric'; - count -------- - 5 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is array'; - count -------- - 2 -(1 row) - -select count(*) from test_jsquery where v @@ '$ is object'; - count -------- - 1017 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; - count -------- - 51 -(1 row) - -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; - count -------- - 1001 -(1 row) - -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; - count -------- - 7 -(1 row) - -select count(*) from test_jsquery where v @@ '$ > 2'; - count -------- - 3 -(1 row) - -select count(*) from test_jsquery where v @@ '$ = false'; - count -------- - 2 -(1 row) - -explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" <@ [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" <@ [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" && [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" && [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; - QUERY PLAN ---------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" @> [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" @> [2, 3]'::jsquery) -(6 rows) - -explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; - QUERY PLAN --------------------------------------------------------------- - Sort - Sort Key: v - -> Bitmap Heap Scan on test_jsquery - Recheck Cond: (v @@ '"array" = [2, 3]'::jsquery) - -> Bitmap Index Scan on t_idx - Index Cond: (v @@ '"array" = [2, 3]'::jsquery) -(6 rows) - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; - v -------------------- - {"array": [2]} - {"array": [2, 3]} -(2 rows) - -select v from test_jsquery where v @@ 'array && [2,3]' order by v; - v ----------------------- - {"array": [2]} - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} - {"array": [3, 4, 5]} -(5 rows) - -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; - v ----------------------- - {"array": [2, 3]} - {"array": [1, 2, 3]} - {"array": [2, 3, 4]} -(3 rows) - -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - v -------------------- - {"array": [2, 3]} -(1 row) - -RESET enable_seqscan; diff --git a/jsquery/jsonb_gin_ops.c b/jsquery/jsonb_gin_ops.c deleted file mode 100644 index 4c6491e63b..0000000000 --- a/jsquery/jsonb_gin_ops.c +++ /dev/null @@ -1,1353 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsonb_gin_ops.c - * Support GIN over jsonb with jsquery operation - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Alexander Korotkov - * - * IDENTIFICATION - * contrib/jsquery/jsonb_gin_ops.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "access/hash.h" -#include "access/skey.h" -#include "catalog/pg_collation.h" -#include "catalog/pg_type.h" -#include "miscadmin.h" -#include "utils/builtins.h" -#include "utils/jsonb.h" - -#include "jsquery.h" - -typedef struct PathHashStack -{ - uint32 hash; - struct PathHashStack *parent; -} PathHashStack; - -typedef struct -{ - int32 vl_len_; - uint32 hash; - uint8 type; - char data[1]; -} GINKey; - -#define GINKEYLEN offsetof(GINKey, data) - -#define GINKeyTrue 0x80 -#define GINKeyMinusInf 0x80 -#define GINKeyEmptyArray 0x80 -#define GINKeyLenString (INTALIGN(offsetof(GINKey, data)) + sizeof(uint32)) -#define GINKeyLenNumeric(len) (INTALIGN(offsetof(GINKey, data)) + len) -#define GINKeyDataString(key) (*(uint32 *)((Pointer)key + INTALIGN(offsetof(GINKey, data)))) -#define GINKeyDataNumeric(key) ((Pointer)key + INTALIGN(offsetof(GINKey, data))) -#define GINKeyType(key) ((key)->type & 0x7F) -#define GINKeyIsTrue(key) ((key)->type & GINKeyTrue) -#define GINKeyIsMinusInf(key) ((key)->type & GINKeyMinusInf) -#define GINKeyIsEmptyArray(key) ((key)->type & GINKeyEmptyArray) - -#define BLOOM_BITS 2 -#define JsonbNestedContainsStrategyNumber 13 -#define JsQueryMatchStrategyNumber 14 - -typedef struct -{ - Datum *entries; - Pointer *extra_data; - bool *partial_match; - int *map; - int count, total; -} Entries; - -typedef struct -{ - ExtractedNode *root; - ExtractedNode *node; - uint32 hash; - bool lossyHash; - GINKey *rightBound; -} KeyExtra; - -static uint32 get_bloom_value(uint32 hash); -static uint32 get_path_bloom(PathHashStack *stack); -static GINKey *make_gin_key(JsonbValue *v, uint32 hash); -static GINKey *make_gin_key_string(uint32 hash); -static GINKey *make_gin_query_value_key(JsQueryItem *value, uint32 hash); -static GINKey *make_gin_query_key(ExtractedNode *node, bool *partialMatch, uint32 hash, KeyExtra *keyExtra); -static GINKey *make_gin_query_key_minus_inf(uint32 hash); -static int32 compare_gin_key_value(GINKey *arg1, GINKey *arg2); -static int add_entry(Entries *e, Datum key, Pointer extra, bool pmatch); - -PG_FUNCTION_INFO_V1(gin_compare_jsonb_value_path); -PG_FUNCTION_INFO_V1(gin_compare_partial_jsonb_value_path); -PG_FUNCTION_INFO_V1(gin_extract_jsonb_value_path); -PG_FUNCTION_INFO_V1(gin_extract_jsonb_query_value_path); -PG_FUNCTION_INFO_V1(gin_consistent_jsonb_value_path); -PG_FUNCTION_INFO_V1(gin_triconsistent_jsonb_value_path); -PG_FUNCTION_INFO_V1(gin_debug_query_value_path); - -Datum gin_compare_jsonb_value_path(PG_FUNCTION_ARGS); -Datum gin_compare_partial_jsonb_value_path(PG_FUNCTION_ARGS); -Datum gin_extract_jsonb_value_path(PG_FUNCTION_ARGS); -Datum gin_extract_jsonb_query_value_path(PG_FUNCTION_ARGS); -Datum gin_consistent_jsonb_value_path(PG_FUNCTION_ARGS); -Datum gin_triconsistent_jsonb_value_path(PG_FUNCTION_ARGS); -Datum gin_debug_query_value_path(PG_FUNCTION_ARGS); - -PG_FUNCTION_INFO_V1(gin_compare_jsonb_path_value); -PG_FUNCTION_INFO_V1(gin_compare_partial_jsonb_path_value); -PG_FUNCTION_INFO_V1(gin_extract_jsonb_path_value); -PG_FUNCTION_INFO_V1(gin_extract_jsonb_query_path_value); -PG_FUNCTION_INFO_V1(gin_consistent_jsonb_path_value); -PG_FUNCTION_INFO_V1(gin_triconsistent_jsonb_path_value); -PG_FUNCTION_INFO_V1(gin_debug_query_path_value); - -Datum gin_compare_jsonb_path_value(PG_FUNCTION_ARGS); -Datum gin_compare_partial_jsonb_path_value(PG_FUNCTION_ARGS); -Datum gin_extract_jsonb_path_value(PG_FUNCTION_ARGS); -Datum gin_extract_jsonb_query_path_value(PG_FUNCTION_ARGS); -Datum gin_consistent_jsonb_path_value(PG_FUNCTION_ARGS); -Datum gin_triconsistent_jsonb_path_value(PG_FUNCTION_ARGS); -Datum gin_debug_query_path_value(PG_FUNCTION_ARGS); - -static int -add_entry(Entries *e, Datum key, Pointer extra, bool pmatch) -{ - int entryNum; - if (!e->entries) - { - e->total = 16; - e->entries = (Datum *)palloc(e->total * sizeof(Datum)); - e->extra_data = (Pointer *)palloc(e->total * sizeof(Pointer)); - e->partial_match = (bool *)palloc(e->total * sizeof(bool)); - } - if (e->count + 1 > e->total) - { - e->total *= 2; - e->entries = (Datum *)repalloc(e->entries, e->total * sizeof(Datum)); - e->extra_data = (Pointer *)repalloc(e->extra_data, e->total * sizeof(Pointer)); - e->partial_match = (bool *)repalloc(e->partial_match, e->total * sizeof(bool)); - } - entryNum = e->count; - e->count++; - e->entries[entryNum] = key; - e->extra_data[entryNum] = extra; - e->partial_match[entryNum] = pmatch; - return entryNum; -} - -static uint32 -get_bloom_value(uint32 hash) -{ - int i, j, vals[BLOOM_BITS], val, tmp; - uint32 res = 0; - for (i = 0; i < BLOOM_BITS; i++) - { - val = hash % (32 - i) + i; - hash /= (32 - i); - vals[i] = val; - - j = i; - while (j > 0 && vals[j] <= vals[j - 1]) - { - tmp = vals[j] - 1; - vals[j] = vals[j - 1]; - vals[j - 1] = tmp; - j--; - } - } - for (i = 0; i < BLOOM_BITS; i++) - { - res |= (1 << vals[i]); - } - return res; -} - -static uint32 -get_path_bloom(PathHashStack *stack) -{ - int i = 0; - uint32 res = 0, val; - - while (stack) - { - uint32 hash = stack->hash; - - val = get_bloom_value(hash); - - res |= val; - i++; - stack = stack->parent; - } - return res; -} - -static uint32 -get_query_path_bloom(PathItem *pathItem, bool *lossy) -{ - uint32 res = 0, val; - - *lossy = false; - while (pathItem) - { - uint32 hash; - - if (pathItem->type == iKey) - { - hash = hash_any((unsigned char *)pathItem->s, pathItem->len); - val = get_bloom_value(hash); - res |= val; - } - else if (pathItem->type == iAny || pathItem->type == iAnyKey) - { - *lossy = true; - } - - pathItem = pathItem->parent; - } - return res; -} - -#ifdef NOT_USED -static void -log_gin_key(GINKey *key) -{ - if (GINKeyType(key) == jbvNull) - { - elog(NOTICE, "hash = %X, NULL", key->hash); - } - else if (GINKeyType(key) == jbvBool) - { - if (GINKeyIsTrue(key)) - elog(NOTICE, "hash = %X, true", key->hash); - else - elog(NOTICE, "hash = %X, false", key->hash); - } - else if (GINKeyType(key) == jbvNumeric) - { - if (GINKeyIsMinusInf(key)) - { - elog(NOTICE, "hash = %X, -inf", key->hash); - } - else - { - char *s; - s = DatumGetCString(DirectFunctionCall1(numeric_out, PointerGetDatum(GINKeyDataNumeric(key)))); - elog(NOTICE, "hash = %X, \"%s\"", key->hash, s); - } - } - else if (GINKeyType(key) == jbvString) - { - elog(NOTICE, "hash = %X, %X", key->hash, GINKeyDataString(key)); - } - else - { - elog(ERROR, "GINKey must be scalar"); - } -} -#endif - -static GINKey * -make_gin_key(JsonbValue *v, uint32 hash) -{ - GINKey *key; - - if (v->type == jbvNull) - { - key = (GINKey *)palloc(GINKEYLEN); - key->type = v->type; - SET_VARSIZE(key, GINKEYLEN); - } - else if (v->type == jbvBool) - { - key = (GINKey *)palloc(GINKEYLEN); - key->type = v->type | (v->val.boolean ? GINKeyTrue : 0); - SET_VARSIZE(key, GINKEYLEN); - } - else if (v->type == jbvArray) - { - key = (GINKey *)palloc(GINKEYLEN); - key->type = v->type; - if (v->val.array.nElems == 0) - key->type |= GINKeyEmptyArray; - SET_VARSIZE(key, GINKEYLEN); - } - else if (v->type == jbvObject) - { - key = (GINKey *)palloc(GINKEYLEN); - key->type = v->type; - SET_VARSIZE(key, GINKEYLEN); - } - else if (v->type == jbvNumeric) - { - key = (GINKey *)palloc(GINKeyLenNumeric(VARSIZE_ANY(v->val.numeric))); - key->type = v->type; - memcpy(GINKeyDataNumeric(key), v->val.numeric, VARSIZE_ANY(v->val.numeric)); - SET_VARSIZE(key, GINKeyLenNumeric(VARSIZE_ANY(v->val.numeric))); - } - else if (v->type == jbvString) - { - key = (GINKey *)palloc(GINKeyLenString); - key->type = v->type; - GINKeyDataString(key) = hash_any((unsigned char *)v->val.string.val, - v->val.string.len); - SET_VARSIZE(key, GINKeyLenString); - } - else - { - elog(ERROR, "GINKey must be scalar"); - } - key->hash = hash; - return key; -} - -static GINKey * -make_gin_key_string(uint32 hash) -{ - GINKey *key; - - key = (GINKey *)palloc(GINKeyLenString); - key->type = jbvString; - GINKeyDataString(key) = 0; - SET_VARSIZE(key, GINKeyLenString); - key->hash = hash; - return key; -} - -static GINKey * -make_gin_query_value_key(JsQueryItem *value, uint32 hash) -{ - GINKey *key; - int32 len; - char *s; - Numeric numeric; - - switch(value->type) - { - case jqiNull: - key = (GINKey *)palloc(GINKEYLEN); - key->type = jbvNull; - SET_VARSIZE(key, GINKEYLEN); - break; - case jqiString: - key = (GINKey *)palloc(GINKeyLenString); - key->type = jbvString; - s = jsqGetString(value, &len); - GINKeyDataString(key) = hash_any((unsigned char *)s, len); - SET_VARSIZE(key, GINKeyLenString); - break; - case jqiBool: - key = (GINKey *)palloc(GINKEYLEN); - key->type = jbvBool | (jsqGetBool(value) ? GINKeyTrue : 0); - SET_VARSIZE(key, GINKEYLEN); - break; - case jqiNumeric: - numeric = jsqGetNumeric(value); - key = (GINKey *)palloc(GINKeyLenNumeric(VARSIZE_ANY(numeric))); - key->type = jbvNumeric; - memcpy(GINKeyDataNumeric(key), numeric, VARSIZE_ANY(numeric)); - SET_VARSIZE(key, GINKeyLenNumeric(VARSIZE_ANY(numeric))); - break; - default: - elog(ERROR,"Wrong state"); - } - - key->hash = hash; - return key; -} - -static GINKey * -make_gin_query_key(ExtractedNode *node, bool *partialMatch, uint32 hash, KeyExtra *keyExtra) -{ - JsonbValue v; - GINKey *key; - - switch (node->type) - { - case eExactValue: - key = make_gin_query_value_key(node->exactValue, hash); - break; - case eEmptyArray: - v.type = jbvArray; - v.val.array.nElems = 0; - key = make_gin_key(&v, hash); - break; - case eInequality: - *partialMatch = true; - if (node->bounds.leftBound) - key = make_gin_query_value_key(node->bounds.leftBound, hash); - else - key = make_gin_query_key_minus_inf(hash); - if (node->bounds.rightBound) - keyExtra->rightBound = make_gin_query_value_key(node->bounds.rightBound, hash); - else - keyExtra->rightBound = NULL; - break; - case eIs: - switch (node->isType) - { - case jbvArray: - *partialMatch = true; - v.type = jbvArray; - v.val.array.nElems = 1; - key = make_gin_key(&v, hash); - break; - case jbvObject: - *partialMatch = true; - v.type = jbvObject; - key = make_gin_key(&v, hash); - break; - case jbvString: - *partialMatch = true; - key = make_gin_key_string(hash); - break; - case jbvNumeric: - *partialMatch = true; - key = make_gin_query_key_minus_inf(hash); - break; - case jbvBool: - *partialMatch = true; - v.type = jbvBool; - v.val.boolean = false; - key = make_gin_key(&v, hash); - break; - case jbvNull: - v.type = jbvNull; - key = make_gin_key(&v, hash); - break; - default: - elog(ERROR,"Wrong type"); - return NULL; - } - break; - case eAny: - v.type = jbvNull; - key = make_gin_key(&v, hash); - *partialMatch = true; - break; - default: - elog(ERROR, "Wrong type"); - break; - } - return key; -} - - -static GINKey * -make_gin_query_key_minus_inf(uint32 hash) -{ - GINKey *key; - - key = (GINKey *)palloc(GINKEYLEN); - key->type = jbvNumeric | GINKeyMinusInf; - key->hash = hash; - SET_VARSIZE(key, GINKEYLEN); - return key; -} - -static bool -check_value_path_entry_handler(ExtractedNode *node, Pointer extra) -{ - return true; -} - -static int -make_value_path_entry_handler(ExtractedNode *node, Pointer extra) -{ - Entries *e = (Entries *)extra; - uint32 hash; - bool lossy, partialMatch = false; - GINKey *key; - KeyExtra *keyExtra; - int result; - - Assert(!isLogicalNodeType(node->type)); - - hash = get_query_path_bloom(node->path, &lossy); - keyExtra = (KeyExtra *)palloc(sizeof(KeyExtra)); - keyExtra->hash = hash; - keyExtra->node = node; - keyExtra->lossyHash = lossy; - - key = make_gin_query_key(node, &partialMatch, hash, keyExtra); - - result = add_entry(e, PointerGetDatum(key), (Pointer)keyExtra, - lossy | partialMatch); - return result; -} - -static int32 -compare_gin_key_value(GINKey *arg1, GINKey *arg2) -{ - if (GINKeyType(arg1) != GINKeyType(arg2)) - { - return (GINKeyType(arg1) > GINKeyType(arg2)) ? 1 : -1; - } - else - { - switch(GINKeyType(arg1)) - { - case jbvNull: - case jbvArray: - if (GINKeyIsEmptyArray(arg1) == GINKeyIsEmptyArray(arg2)) - return 0; - else if (GINKeyIsEmptyArray(arg1) > GINKeyIsEmptyArray(arg2)) - return 1; - else - return -1; - case jbvObject: - return 0; - case jbvBool: - if (GINKeyIsTrue(arg1) == GINKeyIsTrue(arg2)) - return 0; - else if (GINKeyIsTrue(arg1) > GINKeyIsTrue(arg2)) - return 1; - else - return -1; - case jbvNumeric: - if (GINKeyIsMinusInf(arg1)) - { - if (GINKeyIsMinusInf(arg2)) - return 0; - else - return -1; - } - else - { - if (GINKeyIsMinusInf(arg2)) - return 1; - } - return DatumGetInt32(DirectFunctionCall2(numeric_cmp, - PointerGetDatum(GINKeyDataNumeric(arg1)), - PointerGetDatum(GINKeyDataNumeric(arg2)))); - case jbvString: - if (GINKeyDataString(arg1) < GINKeyDataString(arg2)) - return -1; - else if (GINKeyDataString(arg1) == GINKeyDataString(arg2)) - return 0; - else - return 1; - default: - elog(ERROR, "GINKey must be scalar"); - return 0; - } - } -} - -Datum -gin_compare_jsonb_value_path(PG_FUNCTION_ARGS) -{ - GINKey *arg1 = (GINKey *)PG_GETARG_VARLENA_P(0); - GINKey *arg2 = (GINKey *)PG_GETARG_VARLENA_P(1); - int32 result = 0; - - result = compare_gin_key_value(arg1, arg2); - if (result == 0 && arg1->hash != arg2->hash) - { - result = (arg1->hash > arg2->hash) ? 1 : -1; - } - PG_FREE_IF_COPY(arg1, 0); - PG_FREE_IF_COPY(arg2, 1); - PG_RETURN_INT32(result); -} - -Datum -gin_compare_partial_jsonb_value_path(PG_FUNCTION_ARGS) -{ - GINKey *partial_key = (GINKey *)PG_GETARG_VARLENA_P(0); - GINKey *key = (GINKey *)PG_GETARG_VARLENA_P(1); - StrategyNumber strategy = PG_GETARG_UINT16(2); - int32 result; - - if (strategy == JsQueryMatchStrategyNumber) - { - KeyExtra *extra = (KeyExtra *)PG_GETARG_POINTER(3); - ExtractedNode *node = extra->node; - - switch (node->type) - { - case eExactValue: - case eEmptyArray: - result = compare_gin_key_value(key, partial_key); - break; - case eInequality: - result = 0; - if (!node->bounds.leftInclusive && - compare_gin_key_value(key, partial_key) <= 0) - { - result = -1; - } - if (result == 0 && extra->rightBound) - { - result = compare_gin_key_value(key, extra->rightBound); - if ((node->bounds.rightInclusive && result <= 0) - || result < 0) - result = 0; - else - result = 1; - } - break; - case eIs: - if (node->isType == GINKeyType(key)) - result = 0; - else - result = (GINKeyType(key) > node->isType) ? 1 : -1; - break; - case eAny: - result = 0; - break; - default: - elog(ERROR, "Wrong type"); - break; - } - - if (result == 0) - { - if (extra->lossyHash) - { - if ((key->hash & extra->hash) != extra->hash) - result = -1; - } - else - { - if (key->hash != extra->hash) - result = -1; - } - } - } - else - { - uint32 *extra_data = (uint32 *)PG_GETARG_POINTER(3); - uint32 bloom = *extra_data; - - result = compare_gin_key_value(key, partial_key); - - if (result == 0) - { - if ((key->hash & bloom) != bloom) - result = -1; - } - } - - PG_FREE_IF_COPY(partial_key, 0); - PG_FREE_IF_COPY(key, 1); - PG_RETURN_INT32(result); -} - -static Datum * -gin_extract_jsonb_value_path_internal(Jsonb *jb, int32 *nentries, uint32 **bloom) -{ - int total = 2 * JB_ROOT_COUNT(jb); - JsonbIterator *it; - JsonbValue v; - PathHashStack *stack; - int i = 0, - r; - Datum *entries = NULL; - uint32 hash; - - if (total == 0) - { - *nentries = 0; - return NULL; - } - - entries = (Datum *) palloc(sizeof(Datum) * total); - if (bloom) - (*bloom) = (uint32 *) palloc(sizeof(uint32) * total); - - it = JsonbIteratorInit(&jb->root); - - stack = NULL; - - while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) - { - PathHashStack *tmp; - - if (i >= total) - { - total *= 2; - entries = (Datum *) repalloc(entries, sizeof(Datum) * total); - if (bloom) - (*bloom) = (uint32 *) repalloc(*bloom, sizeof(uint32) * total); - } - - switch (r) - { - case WJB_BEGIN_ARRAY: - if (!v.val.array.rawScalar) - entries[i++] = PointerGetDatum(make_gin_key(&v, get_path_bloom(stack))); - break; - case WJB_BEGIN_OBJECT: - entries[i++] = PointerGetDatum(make_gin_key(&v, get_path_bloom(stack))); - tmp = stack; - stack = (PathHashStack *) palloc(sizeof(PathHashStack)); - stack->parent = tmp; - break; - case WJB_KEY: - if (!stack) /* should never happen */ - elog(ERROR, "error jsonb iteration"); - stack->hash = 0; - JsonbHashScalarValue(&v, &stack->hash); - break; - case WJB_ELEM: - case WJB_VALUE: - if (bloom) - { - (*bloom)[i] = get_path_bloom(stack); - hash = 0; - } - else - { - hash = get_path_bloom(stack); - } - entries[i++] = PointerGetDatum(make_gin_key(&v, hash)); - break; - case WJB_END_OBJECT: - /* Pop the stack */ - if (!stack) /* should never happen */ - elog(ERROR, "error jsonb iteration"); - tmp = stack->parent; - pfree(stack); - stack = tmp; - break; - case WJB_END_ARRAY: - break; - default: - elog(ERROR, "invalid JsonbIteratorNext rc: %d", r); - } - } - - *nentries = i; - - return entries; -} - -Datum -gin_extract_jsonb_value_path(PG_FUNCTION_ARGS) -{ - Jsonb *jb = PG_GETARG_JSONB_P(0); - int32 *nentries = (int32 *) PG_GETARG_POINTER(1); - - PG_RETURN_POINTER(gin_extract_jsonb_value_path_internal(jb, nentries, NULL)); -} - -Datum -gin_debug_query_value_path(PG_FUNCTION_ARGS) -{ - JsQuery *jq; - Entries e = {0}; - char *s; - - jq = PG_GETARG_JSQUERY(0); - s = debugJsQuery(jq, make_value_path_entry_handler, - check_value_path_entry_handler, (Pointer)&e); - PG_RETURN_TEXT_P(cstring_to_text(s)); -} - -Datum -gin_extract_jsonb_query_value_path(PG_FUNCTION_ARGS) -{ - Jsonb *jb; - int32 *nentries = (int32 *) PG_GETARG_POINTER(1); - StrategyNumber strategy = PG_GETARG_UINT16(2); - bool **pmatch = (bool **) PG_GETARG_POINTER(3); - Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); - int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); - Datum *entries = NULL; - int i, n; - uint32 *bloom; - Entries e = {0}; - JsQuery *jq; - ExtractedNode *root; - - switch(strategy) - { - case JsonbContainsStrategyNumber: - jb = PG_GETARG_JSONB_P(0); - entries = gin_extract_jsonb_value_path_internal(jb, nentries, NULL); - break; - - case JsonbNestedContainsStrategyNumber: - jb = PG_GETARG_JSONB_P(0); - entries = gin_extract_jsonb_value_path_internal(jb, nentries, &bloom); - - n = *nentries; - *pmatch = (bool *) palloc(sizeof(bool) * n); - for (i = 0; i < n; i++) - (*pmatch)[i] = true; - - *extra_data = (Pointer *) palloc(sizeof(Pointer) * n); - for (i = 0; i < n; i++) - (*extra_data)[i] = (Pointer)&bloom[i]; - break; - - case JsQueryMatchStrategyNumber: - jq = PG_GETARG_JSQUERY(0); - root = extractJsQuery(jq, make_value_path_entry_handler, - check_value_path_entry_handler, (Pointer)&e); - if (root) - { - *nentries = e.count; - entries = e.entries; - *pmatch = e.partial_match; - *extra_data = e.extra_data; - for (i = 0; i < e.count; i++) - ((KeyExtra *)e.extra_data[i])->root = root; - } - else - { - entries = NULL; - *nentries = 0; - } - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - /* ...although "contains {}" requires a full index scan */ - if (entries == NULL) - *searchMode = GIN_SEARCH_MODE_ALL; - - PG_RETURN_POINTER(entries); -} - -Datum -gin_consistent_jsonb_value_path(PG_FUNCTION_ARGS) -{ - bool *check = (bool *) PG_GETARG_POINTER(0); - StrategyNumber strategy = PG_GETARG_UINT16(1); - /* Jsonb *query = PG_GETARG_JSONB_P(2); */ - int32 nkeys = PG_GETARG_INT32(3); - Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); - bool *recheck = (bool *) PG_GETARG_POINTER(5); - bool res = true; - int32 i; - - *recheck = true; - switch (strategy) - { - case JsonbContainsStrategyNumber: - case JsonbNestedContainsStrategyNumber: - for (i = 0; i < nkeys; i++) - { - if (!check[i]) - { - res = false; - break; - } - } - break; - - case JsQueryMatchStrategyNumber: - if (nkeys == 0) - res = true; - else - res = execRecursive(((KeyExtra *)extra_data[0])->root, check); - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - PG_RETURN_BOOL(res); -} - -Datum -gin_triconsistent_jsonb_value_path(PG_FUNCTION_ARGS) -{ - GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0); - StrategyNumber strategy = PG_GETARG_UINT16(1); - /* Jsonb *query = PG_GETARG_JSONB_P(2); */ - int32 nkeys = PG_GETARG_INT32(3); - Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); - GinTernaryValue res = GIN_TRUE; - int32 i; - bool has_maybe = false; - - switch (strategy) - { - case JsonbContainsStrategyNumber: - case JsonbNestedContainsStrategyNumber: - /* - * All extracted keys must be present. A combination of GIN_MAYBE and - * GIN_TRUE induces a GIN_MAYBE result, because then all keys may be - * present. - */ - for (i = 0; i < nkeys; i++) - { - if (check[i] == GIN_FALSE) - { - res = GIN_FALSE; - break; - } - if (check[i] == GIN_MAYBE) - { - res = GIN_MAYBE; - has_maybe = true; - } - } - - /* - * jsonb_hash_ops index doesn't have information about correspondence of - * Jsonb keys and values (as distinct from GIN keys, which for this opclass - * are a hash of a pair, or a hash of just an element), so invariably we - * recheck. This is also reflected in how GIN_MAYBE is given in response - * to there being no GIN_MAYBE input. - */ - if (!has_maybe && res == GIN_TRUE) - res = GIN_MAYBE; - break; - - case JsQueryMatchStrategyNumber: - if (nkeys == 0) - res = GIN_MAYBE; - else - res = execRecursiveTristate(((KeyExtra *)extra_data[0])->root, check); - - if (res == GIN_TRUE) - res = GIN_MAYBE; - - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - PG_RETURN_GIN_TERNARY_VALUE(res); -} - -static bool -get_query_path_hash(PathItem *pathItem, uint32 *hash) -{ - check_stack_depth(); - - if (!pathItem) - return true; - - if (!get_query_path_hash(pathItem->parent, hash)) - { - return false; - } - else - { - if (pathItem->type == iAny || pathItem->type == iAnyKey) - { - return false; - } - else - { - if (pathItem->type == iKey) - { - *hash = (*hash << 1) | (*hash >> 31); - *hash ^= hash_any((unsigned char *)pathItem->s, pathItem->len); - } - else if (pathItem->type == iAnyArray || pathItem->type == iIndexArray) - { - *hash = (*hash << 1) | (*hash >> 31); - *hash ^= JB_FARRAY; - } - return true; - } - } -} - -static bool -check_path_value_entry_handler(ExtractedNode *node, Pointer extra) -{ - uint32 hash; - hash = 0; - if (!get_query_path_hash(node->path, &hash)) - return false; - return true; -} - -static int -make_path_value_entry_handler(ExtractedNode *node, Pointer extra) -{ - Entries *e = (Entries *)extra; - uint32 hash; - GINKey *key; - KeyExtra *keyExtra; - int result; - bool partialMatch = false; - - Assert(!isLogicalNodeType(node->type)); - - hash = 0; - if (!get_query_path_hash(node->path, &hash)) - return -1; - - keyExtra = (KeyExtra *)palloc(sizeof(KeyExtra)); - keyExtra->hash = hash; - keyExtra->node = node; - key = make_gin_query_key(node, &partialMatch, hash, keyExtra); - - result = add_entry(e, PointerGetDatum(key), (Pointer)keyExtra, partialMatch); - return result; -} - -Datum -gin_compare_jsonb_path_value(PG_FUNCTION_ARGS) -{ - GINKey *arg1 = (GINKey *)PG_GETARG_VARLENA_P(0); - GINKey *arg2 = (GINKey *)PG_GETARG_VARLENA_P(1); - int32 result = 0; - - if (arg1->hash != arg2->hash) - { - result = (arg1->hash > arg2->hash) ? 1 : -1; - } - else - { - result = compare_gin_key_value(arg1, arg2); - } - PG_FREE_IF_COPY(arg1, 0); - PG_FREE_IF_COPY(arg2, 1); - PG_RETURN_INT32(result); -} - -Datum -gin_compare_partial_jsonb_path_value(PG_FUNCTION_ARGS) -{ - GINKey *partial_key = (GINKey *)PG_GETARG_VARLENA_P(0); - GINKey *key = (GINKey *)PG_GETARG_VARLENA_P(1); - StrategyNumber strategy = PG_GETARG_UINT16(2); - int32 result; - - if (key->hash != partial_key->hash) - { - result = (key->hash > partial_key->hash) ? 1 : -1; - } - else if (strategy == JsQueryMatchStrategyNumber) - { - KeyExtra *extra = (KeyExtra *)PG_GETARG_POINTER(3); - ExtractedNode *node = extra->node; - - switch (node->type) - { - case eInequality: - result = 0; - if (!node->bounds.leftInclusive && - compare_gin_key_value(key, partial_key) <= 0) - { - result = -1; - } - if (result == 0 && extra->rightBound) - { - result = compare_gin_key_value(key, extra->rightBound); - if ((node->bounds.rightInclusive && result <= 0) - || result < 0) - result = 0; - else - result = 1; - } - break; - case eIs: - if (node->isType == GINKeyType(key)) - result = 0; - else - result = (GINKeyType(key) > node->isType) ? 1 : -1; - break; - case eAny: - result = 0; - break; - default: - elog(ERROR, "Wrong type"); - break; - } - } - else - { - result = compare_gin_key_value(key, partial_key); - } - - PG_FREE_IF_COPY(partial_key, 0); - PG_FREE_IF_COPY(key, 1); - PG_RETURN_INT32(result); -} - -static Datum * -gin_extract_jsonb_path_value_internal(Jsonb *jb, int32 *nentries) -{ - int total = 2 * JB_ROOT_COUNT(jb); - JsonbIterator *it; - JsonbValue v; - PathHashStack tail; - PathHashStack *stack; - int i = 0, - r; - Datum *entries = NULL; - - if (total == 0) - { - *nentries = 0; - return NULL; - } - - entries = (Datum *) palloc(sizeof(Datum) * total); - - it = JsonbIteratorInit(&jb->root); - - tail.parent = NULL; - tail.hash = 0; - stack = &tail; - - while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) - { - PathHashStack *tmp; - - if (i >= total) - { - total *= 2; - entries = (Datum *) repalloc(entries, sizeof(Datum) * total); - } - - if (!stack) /* should never happen */ - elog(ERROR, "error jsonb iteration"); - - switch (r) - { - case WJB_BEGIN_ARRAY: - if (v.val.array.rawScalar) - break; - entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); - tmp = stack; - stack = (PathHashStack *) palloc(sizeof(PathHashStack)); - stack->parent = tmp; - stack->hash = stack->parent->hash; - stack->hash = (stack->hash << 1) | (stack->hash >> 31); - stack->hash ^= JB_FARRAY; - break; - case WJB_BEGIN_OBJECT: - entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); - tmp = stack; - stack = (PathHashStack *) palloc(sizeof(PathHashStack)); - stack->parent = tmp; - stack->hash = stack->parent->hash; - break; - case WJB_KEY: - /* Initialize hash from parent */ - if (!stack->parent) /* should never happen */ - elog(ERROR, "error jsonb iteration"); - stack->hash = stack->parent->hash; - JsonbHashScalarValue(&v, &stack->hash); - break; - case WJB_ELEM: - case WJB_VALUE: - /* Element/value case */ - entries[i++] = PointerGetDatum(make_gin_key(&v, stack->hash)); - break; - case WJB_END_ARRAY: - if (!stack->parent) - break; /* raw scalar array */ - /* fall through */ - case WJB_END_OBJECT: - /* Pop the stack */ - tmp = stack->parent; - pfree(stack); - stack = tmp; - break; - default: - elog(ERROR, "invalid JsonbIteratorNext rc: %d", r); - } - } - - *nentries = i; - - return entries; -} - -Datum -gin_extract_jsonb_path_value(PG_FUNCTION_ARGS) -{ - Jsonb *jb = PG_GETARG_JSONB_P(0); - int32 *nentries = (int32 *) PG_GETARG_POINTER(1); - - PG_RETURN_POINTER(gin_extract_jsonb_path_value_internal(jb, nentries)); -} - -Datum -gin_debug_query_path_value(PG_FUNCTION_ARGS) -{ - JsQuery *jq; - Entries e = {0}; - char *s; - - - jq = PG_GETARG_JSQUERY(0); - s = debugJsQuery(jq, make_path_value_entry_handler, - check_path_value_entry_handler, (Pointer)&e); - PG_RETURN_TEXT_P(cstring_to_text(s)); -} - -Datum -gin_extract_jsonb_query_path_value(PG_FUNCTION_ARGS) -{ - Jsonb *jb; - int32 *nentries = (int32 *) PG_GETARG_POINTER(1); - StrategyNumber strategy = PG_GETARG_UINT16(2); - bool **pmatch = (bool **) PG_GETARG_POINTER(3); - Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); - int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); - Datum *entries = NULL; - int i; - Entries e = {0}; - JsQuery *jq; - ExtractedNode *root; - - switch(strategy) - { - case JsonbContainsStrategyNumber: - jb = PG_GETARG_JSONB_P(0); - entries = gin_extract_jsonb_path_value_internal(jb, nentries); - break; - - case JsQueryMatchStrategyNumber: - jq = PG_GETARG_JSQUERY(0); - root = extractJsQuery(jq, make_path_value_entry_handler, - check_path_value_entry_handler, (Pointer)&e); - if (root) - { - *nentries = e.count; - entries = e.entries; - *pmatch = e.partial_match; - *extra_data = e.extra_data; - for (i = 0; i < e.count; i++) - ((KeyExtra *)e.extra_data[i])->root = root; - } - else - { - entries = NULL; - *nentries = 0; - } - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - /* ...although "contains {}" requires a full index scan */ - if (entries == NULL) - *searchMode = GIN_SEARCH_MODE_ALL; - - PG_RETURN_POINTER(entries); -} - -Datum -gin_consistent_jsonb_path_value(PG_FUNCTION_ARGS) -{ - bool *check = (bool *) PG_GETARG_POINTER(0); - StrategyNumber strategy = PG_GETARG_UINT16(1); - /* Jsonb *query = PG_GETARG_JSONB_P(2); */ - int32 nkeys = PG_GETARG_INT32(3); - Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); - bool *recheck = (bool *) PG_GETARG_POINTER(5); - bool res = true; - int32 i; - - *recheck = true; - switch (strategy) - { - case JsonbContainsStrategyNumber: - for (i = 0; i < nkeys; i++) - { - if (!check[i]) - { - res = false; - break; - } - } - break; - - case JsQueryMatchStrategyNumber: - if (nkeys == 0) - res = true; - else - res = execRecursive(((KeyExtra *)extra_data[0])->root, check); - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - PG_RETURN_BOOL(res); -} - -Datum -gin_triconsistent_jsonb_path_value(PG_FUNCTION_ARGS) -{ - GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0); - StrategyNumber strategy = PG_GETARG_UINT16(1); - /* Jsonb *query = PG_GETARG_JSONB_P(2); */ - int32 nkeys = PG_GETARG_INT32(3); - Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); - GinTernaryValue res = GIN_TRUE; - int32 i; - bool has_maybe = false; - - - switch (strategy) - { - case JsonbContainsStrategyNumber: - /* - * All extracted keys must be present. A combination of GIN_MAYBE and - * GIN_TRUE induces a GIN_MAYBE result, because then all keys may be - * present. - */ - for (i = 0; i < nkeys; i++) - { - if (check[i] == GIN_FALSE) - { - res = GIN_FALSE; - break; - } - if (check[i] == GIN_MAYBE) - { - res = GIN_MAYBE; - has_maybe = true; - } - } - - /* - * jsonb_hash_ops index doesn't have information about correspondence of - * Jsonb keys and values (as distinct from GIN keys, which for this opclass - * are a hash of a pair, or a hash of just an element), so invariably we - * recheck. This is also reflected in how GIN_MAYBE is given in response - * to there being no GIN_MAYBE input. - */ - if (!has_maybe && res == GIN_TRUE) - res = GIN_MAYBE; - break; - - case JsQueryMatchStrategyNumber: - if (nkeys == 0) - res = GIN_MAYBE; - else - res = execRecursiveTristate(((KeyExtra *)extra_data[0])->root, check); - - if (res == GIN_TRUE) - res = GIN_MAYBE; - - break; - - default: - elog(ERROR, "unrecognized strategy number: %d", strategy); - break; - } - - PG_RETURN_GIN_TERNARY_VALUE(res); -} - diff --git a/jsquery/jsquery--1.0.sql b/jsquery/jsquery--1.0.sql deleted file mode 100644 index 3bf1d9bc17..0000000000 --- a/jsquery/jsquery--1.0.sql +++ /dev/null @@ -1,293 +0,0 @@ --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION jsquery" to load this file. \quit - -CREATE TYPE jsquery; - -CREATE FUNCTION jsquery_in(cstring) - RETURNS jsquery - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_out(jsquery) - RETURNS cstring - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE TYPE jsquery ( - INTERNALLENGTH = -1, - INPUT = jsquery_in, - OUTPUT = jsquery_out, - STORAGE = extended -); - -CREATE FUNCTION jsquery_json_exec(jsquery, jsonb) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION json_jsquery_exec(jsonb, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR @@ ( - LEFTARG = jsquery, - RIGHTARG = jsonb, - PROCEDURE = jsquery_json_exec, - COMMUTATOR = '@@', - RESTRICT = contsel, - JOIN = contjoinsel -); - -CREATE OPERATOR @@ ( - LEFTARG = jsonb, - RIGHTARG = jsquery, - PROCEDURE = json_jsquery_exec, - COMMUTATOR = '@@', - RESTRICT = contsel, - JOIN = contjoinsel -); - -CREATE FUNCTION jsquery_join_and(jsquery, jsquery) - RETURNS jsquery - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR & ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_join_and, - COMMUTATOR = '&' -); - -CREATE FUNCTION jsquery_join_or(jsquery, jsquery) - RETURNS jsquery - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR | ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_join_or, - COMMUTATOR = '|' -); - -CREATE FUNCTION jsquery_not(jsquery) - RETURNS jsquery - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR ! ( - RIGHTARG = jsquery, - PROCEDURE = jsquery_not -); - -CREATE FUNCTION jsquery_lt(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_le(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_eq(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_ne(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_ge(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE FUNCTION jsquery_gt(jsquery, jsquery) - RETURNS bool - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR < ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_lt, - COMMUTATOR = '>', - NEGATOR = '>=', - RESTRICT = scalarltsel, - JOIN = scalarltjoinsel -); - -CREATE OPERATOR <= ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_le, - COMMUTATOR = '>=', - NEGATOR = '>', - RESTRICT = scalarltsel, - JOIN = scalarltjoinsel -); - -CREATE OPERATOR = ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_eq, - COMMUTATOR = '=', - NEGATOR = '<>', - RESTRICT = eqsel, - JOIN = eqjoinsel, - HASHES, - MERGES -); - -CREATE OPERATOR <> ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_eq, - COMMUTATOR = '<>', - NEGATOR = '=', - RESTRICT = neqsel, - JOIN = neqjoinsel -); - -CREATE OPERATOR >= ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_ge, - COMMUTATOR = '<=', - NEGATOR = '<', - RESTRICT = scalargtsel, - JOIN = scalargtjoinsel -); - -CREATE OPERATOR > ( - LEFTARG = jsquery, - RIGHTARG = jsquery, - PROCEDURE = jsquery_ge, - COMMUTATOR = '<', - NEGATOR = '<=', - RESTRICT = scalargtsel, - JOIN = scalargtjoinsel -); - -CREATE FUNCTION jsquery_cmp(jsquery, jsquery) - RETURNS int4 - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR CLASS jsquery_ops - DEFAULT FOR TYPE jsquery USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 >, - FUNCTION 1 jsquery_cmp(jsquery, jsquery); - -CREATE FUNCTION jsquery_hash(jsquery) - RETURNS int4 - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR CLASS jsquery_ops - DEFAULT FOR TYPE jsquery USING hash AS - OPERATOR 1 =, - FUNCTION 1 jsquery_hash(jsquery); - -CREATE OR REPLACE FUNCTION gin_compare_jsonb_value_path(bytea, bytea) - RETURNS integer - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_compare_partial_jsonb_value_path(bytea, bytea, smallint, internal) - RETURNS integer - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_extract_jsonb_value_path(internal, internal, internal) - RETURNS internal - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_extract_jsonb_query_value_path(anyarray, internal, smallint, internal, internal, internal, internal) - RETURNS internal - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_consistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal, internal) - RETURNS boolean - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_triconsistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal) - RETURNS boolean - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR CLASS jsonb_value_path_ops - FOR TYPE jsonb USING gin AS - OPERATOR 7 @>, - OPERATOR 14 @@ (jsonb, jsquery), - FUNCTION 1 gin_compare_jsonb_value_path(bytea, bytea), - FUNCTION 2 gin_extract_jsonb_value_path(internal, internal, internal), - FUNCTION 3 gin_extract_jsonb_query_value_path(anyarray, internal, smallint, internal, internal, internal, internal), - FUNCTION 4 gin_consistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal, internal), - FUNCTION 5 gin_compare_partial_jsonb_value_path(bytea, bytea, smallint, internal), - FUNCTION 6 gin_triconsistent_jsonb_value_path(internal, smallint, anyarray, integer, internal, internal, internal), - STORAGE bytea; - -CREATE OR REPLACE FUNCTION gin_compare_jsonb_path_value(bytea, bytea) - RETURNS integer - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_compare_partial_jsonb_path_value(bytea, bytea, smallint, internal) - RETURNS integer - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_extract_jsonb_path_value(internal, internal, internal) - RETURNS internal - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_extract_jsonb_query_path_value(anyarray, internal, smallint, internal, internal, internal, internal) - RETURNS internal - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_consistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal, internal) - RETURNS boolean - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_triconsistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal) - RETURNS boolean - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OPERATOR CLASS jsonb_path_value_ops - FOR TYPE jsonb USING gin AS - OPERATOR 7 @>, - OPERATOR 14 @@ (jsonb, jsquery), - FUNCTION 1 gin_compare_jsonb_path_value(bytea, bytea), - FUNCTION 2 gin_extract_jsonb_path_value(internal, internal, internal), - FUNCTION 3 gin_extract_jsonb_query_path_value(anyarray, internal, smallint, internal, internal, internal, internal), - FUNCTION 4 gin_consistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal, internal), - FUNCTION 5 gin_compare_partial_jsonb_path_value(bytea, bytea, smallint, internal), - FUNCTION 6 gin_triconsistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal), - STORAGE bytea; - -CREATE OR REPLACE FUNCTION gin_debug_query_value_path(jsquery) - RETURNS text - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE OR REPLACE FUNCTION gin_debug_query_path_value(jsquery) - RETURNS text - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; diff --git a/jsquery/jsquery.control b/jsquery/jsquery.control deleted file mode 100644 index 94510c82cc..0000000000 --- a/jsquery/jsquery.control +++ /dev/null @@ -1,6 +0,0 @@ -# jsquery extension -comment = 'data type for jsonb inspection' -default_version = '1.0' -module_pathname = '$libdir/jsquery' -relocatable = true - diff --git a/jsquery/jsquery.h b/jsquery/jsquery.h deleted file mode 100644 index d98dd6c5c4..0000000000 --- a/jsquery/jsquery.h +++ /dev/null @@ -1,249 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery.h - * Definitions of jsquery datatype - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery.h - * - *------------------------------------------------------------------------- - */ - -#ifndef __JSQUERY_H__ -#define __JSQUERY_H__ - -#include "access/gin.h" -#include "fmgr.h" -#include "utils/numeric.h" -#include "utils/jsonb.h" - -typedef struct -{ - int32 vl_len_; /* varlena header (do not touch directly!) */ -} JsQuery; - -#define DatumGetJsQueryP(d) ((JsQuery*)DatumGetPointer(PG_DETOAST_DATUM(d))) -#define PG_GETARG_JSQUERY(x) DatumGetJsQueryP(PG_GETARG_DATUM(x)) -#define PG_RETURN_JSQUERY(p) PG_RETURN_POINTER(p) - -typedef enum JsQueryItemType { - jqiNull = jbvNull, - jqiString = jbvString, - jqiNumeric = jbvNumeric, - jqiBool = jbvBool, - jqiArray = jbvArray, - jqiAnd, - jqiOr, - jqiNot, - jqiEqual, - jqiLess, - jqiGreater, - jqiLessOrEqual, - jqiGreaterOrEqual, - jqiContains, - jqiContained, - jqiOverlap, - jqiAny, - jqiAnyArray, - jqiAnyKey, - jqiAll, - jqiAllArray, - jqiAllKey, - jqiKey, - jqiCurrent, - jqiLength, - jqiIn, - jqiIs, - jqiIndexArray -} JsQueryItemType; - -/* - * JsQueryHint is stored in the same byte as JsQueryItemType so - * JsQueryItemType should not use two high bits - */ -typedef enum JsQueryHint { - jsqIndexDefault = 0x00, - jsqForceIndex = 0x80, - jsqNoIndex = 0x40 -} JsQueryHint; - -#define JSQ_HINT_MASK (jsqIndexDefault | jsqForceIndex | jsqNoIndex) - -/* - * Support functions to parse/construct binary value. - * Unlike many other representation of expression the first/main - * node is not an operation but left operand of expression. That - * allows to implement cheep follow-path descending in jsonb - * structure and then execute operator with right operand which - * is always a constant. - */ - -typedef struct JsQueryItem { - JsQueryItemType type; - JsQueryHint hint; - int32 nextPos; - char *base; - - union { - struct { - char *data; /* for bool, numeric and string/key */ - int datalen; /* filled only for string/key */ - } value; - - struct { - int32 left; - int32 right; - } args; - - int32 arg; - - struct { - int nelems; - int current; - int32 *arrayPtr; - } array; - - uint32 arrayIndex; - }; -} JsQueryItem; - -extern void jsqInit(JsQueryItem *v, JsQuery *js); -extern void jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos); -extern bool jsqGetNext(JsQueryItem *v, JsQueryItem *a); -extern void jsqGetArg(JsQueryItem *v, JsQueryItem *a); -extern void jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a); -extern void jsqGetRightArg(JsQueryItem *v, JsQueryItem *a); -extern Numeric jsqGetNumeric(JsQueryItem *v); -extern bool jsqGetBool(JsQueryItem *v); -extern int32 jsqGetIsType(JsQueryItem *v); -extern char * jsqGetString(JsQueryItem *v, int32 *len); -extern void jsqIterateInit(JsQueryItem *v); -extern bool jsqIterateArray(JsQueryItem *v, JsQueryItem *e); - -void alignStringInfoInt(StringInfo buf); - -/* - * Parsing - */ - -typedef struct JsQueryParseItem JsQueryParseItem; - -struct JsQueryParseItem { - JsQueryItemType type; - JsQueryHint hint; - JsQueryParseItem *next; /* next in path */ - - union { - struct { - JsQueryParseItem *left; - JsQueryParseItem *right; - } args; - - JsQueryParseItem *arg; - int8 isType; /* jbv* values */ - - Numeric numeric; - bool boolean; - struct { - uint32 len; - char *val; /* could not be not null-terminated */ - } string; - - struct { - int nelems; - JsQueryParseItem **elems; - } array; - - uint32 arrayIndex; - }; -}; - -extern JsQueryParseItem* parsejsquery(const char *str, int len); - -/* jsquery_extract.c */ - -typedef enum -{ - iAny = jqiAny, - iAnyArray = jqiAnyArray, - iKey = jqiKey, - iAnyKey = jqiAnyKey, - iIndexArray = jqiIndexArray -} PathItemType; - -typedef struct PathItem PathItem; -struct PathItem -{ - PathItemType type; - int len; - int arrayIndex; - char *s; - PathItem *parent; -}; - -typedef enum -{ - eExactValue = 1, - eEmptyArray, - eInequality, - eIs, - eAny, - eAnd = jqiAnd, - eOr = jqiOr, -} ExtractedNodeType; - -typedef enum -{ - sEqual = 1, - sRange, - sInequal, - sIs, - sAny -} SelectivityClass; - -typedef struct ExtractedNode ExtractedNode; -struct ExtractedNode -{ - ExtractedNodeType type; - JsQueryHint hint; - PathItem *path; - bool indirect; - SelectivityClass sClass; - bool forceIndex; - int number; - int entryNum; - union - { - struct - { - ExtractedNode **items; - int count; - } args; - struct - { - bool leftInclusive; - bool rightInclusive; - JsQueryItem *leftBound; - JsQueryItem *rightBound; - } bounds; - JsQueryItem *exactValue; - int32 isType; - }; -}; - -typedef int (*MakeEntryHandler)(ExtractedNode *node, Pointer extra); -typedef bool (*CheckEntryHandler)(ExtractedNode *node, Pointer extra); -bool isLogicalNodeType(ExtractedNodeType type); - -ExtractedNode *extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, - CheckEntryHandler checkHandler, Pointer extra); -char *debugJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, - CheckEntryHandler checkHandler, Pointer extra); -bool queryNeedRecheck(ExtractedNode *node); -bool execRecursive(ExtractedNode *node, bool *check); -bool execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check); - -#endif diff --git a/jsquery/jsquery_constr.c b/jsquery/jsquery_constr.c deleted file mode 100644 index fcb9088758..0000000000 --- a/jsquery/jsquery_constr.c +++ /dev/null @@ -1,260 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_constr.c - * Functions and operations to manipulate jsquery - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_constr.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "miscadmin.h" -#include "utils/builtins.h" - -#include "jsquery.h" - -static int32 -copyJsQuery(StringInfo buf, JsQueryItem *jsq) -{ - JsQueryItem elem; - int32 next, chld; - int32 resPos = buf->len - VARHDRSZ; /* position from begining of jsquery data */ - - check_stack_depth(); - - Assert((jsq->type & jsq->hint) == 0); - Assert((jsq->type & JSQ_HINT_MASK) == 0); - - appendStringInfoChar(buf, (char)(jsq->type | jsq->hint)); - alignStringInfoInt(buf); - - next = (jsqGetNext(jsq, NULL)) ? buf->len : 0; - appendBinaryStringInfo(buf, (char*)&next /* fake value */, sizeof(next)); - - switch(jsq->type) - { - case jqiKey: - case jqiString: - { - int32 len; - char *s; - - s = jsqGetString(jsq, &len); - appendBinaryStringInfo(buf, (char*)&len, sizeof(len)); - appendBinaryStringInfo(buf, s, len + 1 /* \0 */); - } - break; - case jqiNumeric: - { - Numeric n = jsqGetNumeric(jsq); - - appendBinaryStringInfo(buf, (char*)n, VARSIZE_ANY(n)); - } - break; - case jqiBool: - { - bool v = jsqGetBool(jsq); - - appendBinaryStringInfo(buf, (char*)&v, 1); - } - break; - case jqiArray: - { - int32 i, arrayStart; - - appendBinaryStringInfo(buf, (char*)&jsq->array.nelems, - sizeof(jsq->array.nelems)); - - arrayStart = buf->len; - - /* reserve place for "pointers" to array's elements */ - for(i=0; iarray.nelems; i++) - appendBinaryStringInfo(buf, (char*)&i /* fake value */, sizeof(i)); - - while(jsqIterateArray(jsq, &elem)) - { - chld = copyJsQuery(buf, &elem); - *(int32*)(buf->data + arrayStart + i * sizeof(i)) = chld; - i++; - } - } - break; - case jqiAnd: - case jqiOr: - { - int32 leftOut, rightOut; - - leftOut = buf->len; - appendBinaryStringInfo(buf, (char*)&leftOut /* fake value */, sizeof(leftOut)); - rightOut = buf->len; - appendBinaryStringInfo(buf, (char*)&rightOut /* fake value */, sizeof(rightOut)); - - jsqGetLeftArg(jsq, &elem); - chld = copyJsQuery(buf, &elem); - *(int32*)(buf->data + leftOut) = chld; - - jsqGetRightArg(jsq, &elem); - chld = copyJsQuery(buf, &elem); - *(int32*)(buf->data + rightOut) = chld; - } - break; - case jqiEqual: - case jqiIn: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - case jqiNot: - { - int32 argOut = buf->len; - - appendBinaryStringInfo(buf, (char*)&argOut /* fake value */, sizeof(argOut)); - - jsqGetArg(jsq, &elem); - chld = copyJsQuery(buf, &elem); - *(int32*)(buf->data + argOut) = chld; - } - break; - case jqiIndexArray: - appendBinaryStringInfo(buf, (char*)&jsq->arrayIndex, - sizeof(jsq->arrayIndex)); - break; - case jqiNull: - case jqiCurrent: - case jqiLength: - case jqiAny: - case jqiAnyArray: - case jqiAnyKey: - case jqiAll: - case jqiAllArray: - case jqiAllKey: - break; - default: - elog(ERROR, "Unknown type: %d", jsq->type); - } - - if (jsqGetNext(jsq, &elem)) - *(int32*)(buf->data + next) = copyJsQuery(buf, &elem); - - return resPos; -} - -static JsQuery* -joinJsQuery(JsQueryItemType type, JsQuery *jq1, JsQuery *jq2) -{ - JsQuery *out; - StringInfoData buf; - int32 left, right, chld; - JsQueryItem v; - - initStringInfo(&buf); - enlargeStringInfo(&buf, VARSIZE_ANY(jq1) + VARSIZE_ANY(jq2) + 4 * sizeof(int32) + VARHDRSZ); - - appendStringInfoSpaces(&buf, VARHDRSZ); - - /* form jqiAnd/jqiOr header */ - appendStringInfoChar(&buf, (char)type); - alignStringInfoInt(&buf); - - /* nextPos field of header*/ - chld = 0; /* actual value, not a fake */ - appendBinaryStringInfo(&buf, (char*)&chld, sizeof(chld)); - - left = buf.len; - appendBinaryStringInfo(&buf, (char*)&left /* fake value */, sizeof(left)); - right = buf.len; - appendBinaryStringInfo(&buf, (char*)&right /* fake value */, sizeof(right)); - - /* dump left and right subtree */ - jsqInit(&v, jq1); - chld = copyJsQuery(&buf, &v); - *(int32*)(buf.data + left) = chld; - jsqInit(&v, jq2); - chld = copyJsQuery(&buf, &v); - *(int32*)(buf.data + right) = chld; - - out = (JsQuery*)buf.data; - SET_VARSIZE(out, buf.len); - - return out; -} - -PG_FUNCTION_INFO_V1(jsquery_join_and); -Datum -jsquery_join_and(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - JsQuery *out; - - out = joinJsQuery(jqiAnd, jq1, jq2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_JSQUERY(out); -} - -PG_FUNCTION_INFO_V1(jsquery_join_or); -Datum -jsquery_join_or(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - JsQuery *out; - - out = joinJsQuery(jqiOr, jq1, jq2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_JSQUERY(out); -} - -PG_FUNCTION_INFO_V1(jsquery_not); -Datum -jsquery_not(PG_FUNCTION_ARGS) -{ - JsQuery *jq = PG_GETARG_JSQUERY(0); - JsQuery *out; - StringInfoData buf; - int32 arg, chld; - JsQueryItem v; - - initStringInfo(&buf); - enlargeStringInfo(&buf, VARSIZE_ANY(jq) + 4 * sizeof(int32) + VARHDRSZ); - - appendStringInfoSpaces(&buf, VARHDRSZ); - - /* form jsquery header */ - appendStringInfoChar(&buf, (char)jqiNot); - alignStringInfoInt(&buf); - - /* nextPos field of header*/ - chld = 0; /* actual value, not a fake */ - appendBinaryStringInfo(&buf, (char*)&chld, sizeof(chld)); - - arg = buf.len; - appendBinaryStringInfo(&buf, (char*)&arg /* fake value */, sizeof(arg)); - - jsqInit(&v, jq); - chld = copyJsQuery(&buf, &v); - *(int32*)(buf.data + arg) = chld; - - out = (JsQuery*)buf.data; - SET_VARSIZE(out, buf.len); - - PG_FREE_IF_COPY(jq, 0); - - PG_RETURN_JSQUERY(out); -} - diff --git a/jsquery/jsquery_extract.c b/jsquery/jsquery_extract.c deleted file mode 100644 index 01956ae0bd..0000000000 --- a/jsquery/jsquery_extract.c +++ /dev/null @@ -1,1021 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_extract.c - * Functions and operations to support jsquery in indexes - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Alexander Korotkov - * - * IDENTIFICATION - * contrib/jsquery/jsquery_extract.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "access/gin.h" -#include "utils/builtins.h" -#include "utils/jsonb.h" - -#include "miscadmin.h" -#include "jsquery.h" - -static ExtractedNode *recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path); -static int coundChildren(ExtractedNode *node, ExtractedNodeType type, bool first, bool *found); -static void fillChildren(ExtractedNode *node, ExtractedNodeType type, bool first, ExtractedNode **items, int *i); -static void flatternTree(ExtractedNode *node); -static int comparePathItems(PathItem *i1, PathItem *i2); -static int compareNodes(const void *a1, const void *a2); -static int compareJsQueryItem(JsQueryItem *v1, JsQueryItem *v2); -static void processGroup(ExtractedNode *node, int start, int end); -static void simplifyRecursive(ExtractedNode *node); -static SelectivityClass getScalarSelectivityClass(ExtractedNode *node); -static ExtractedNode *makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra); -static void setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler, Pointer extra); -static void debugPath(StringInfo buf, PathItem *path); -static void debugValue(StringInfo buf, JsQueryItem *v); -static void debugRecursive(StringInfo buf, ExtractedNode *node, int shift); - -/* - * Recursive function that turns jsquery into tree of ExtractedNode items. - */ -static ExtractedNode * -recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path) -{ - ExtractedNode *leftNode, *rightNode, *result; - PathItem *pathItem; - ExtractedNodeType type; - JsQueryItem elem, e; - - e.hint = false; - check_stack_depth(); - - switch(jsq->type) - { - case jqiAnd: - case jqiOr: - type = ((jsq->type == jqiAnd) == not) ? eOr : eAnd; - - jsqGetLeftArg(jsq, &elem); - leftNode = recursiveExtract(&elem, not, false, path); - jsqGetRightArg(jsq, &elem); - rightNode = recursiveExtract(&elem, not, false, path); - - if (!leftNode || !rightNode) - { - if (type == eOr || (!leftNode && !rightNode)) - return NULL; - if (leftNode) - { - leftNode->indirect = leftNode->indirect || indirect; - return leftNode; - } - else - { - rightNode->indirect = rightNode->indirect || indirect; - return rightNode; - } - } - - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = type; - result->path = path; - result->indirect = indirect; - result->args.items = (ExtractedNode **)palloc(2 * sizeof(ExtractedNode *)); - result->args.items[0] = leftNode; - result->args.items[1] = rightNode; - result->args.count = 2; - return result; - case jqiNot: - jsqGetArg(jsq, &elem); - return recursiveExtract(&elem, !not, indirect, path); - case jqiKey: - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iKey; - pathItem->s = jsqGetString(jsq, &pathItem->len); - pathItem->parent = path; - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, indirect, pathItem); - case jqiAny: - case jqiAll: - if ((not && jsq->type == jqiAny) || (!not && jsq->type == jqiAll)) - return NULL; - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iAny; - pathItem->parent = path; - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, true, pathItem); - case jqiIndexArray: - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iIndexArray; - pathItem->arrayIndex = jsq->arrayIndex; - pathItem->parent = path; - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, true, pathItem); - case jqiAnyArray: - case jqiAllArray: - if ((not && jsq->type == jqiAnyArray) || (!not && jsq->type == jqiAllArray)) - return NULL; - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iAnyArray; - pathItem->parent = path; - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, true, pathItem); - case jqiAnyKey: - case jqiAllKey: - if ((not && jsq->type == jqiAnyKey) || (!not && jsq->type == jqiAllKey)) - return NULL; - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iAnyKey; - pathItem->parent = path; - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, true, pathItem); - case jqiCurrent: - jsqGetNext(jsq, &elem); - return recursiveExtract(&elem, not, indirect, path); - case jqiEqual: - if (not) - return NULL; - jsqGetArg(jsq, &e); - if (e.type == jqiAny) - { - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = eAny; - result->hint = jsq->hint; - result->path = path; - result->indirect = indirect; - return result; - } - else if (e.type != jqiArray) - { - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = eExactValue; - result->hint = jsq->hint; - result->path = path; - result->indirect = indirect; - result->exactValue = (JsQueryItem *)palloc(sizeof(JsQueryItem)); - *result->exactValue = e; - return result; - } - /* jqiEqual with jqiArray follows */ - case jqiIn: - case jqiOverlap: - case jqiContains: - case jqiContained: - if (not) - return NULL; - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = (jsq->type == jqiContains || jsq->type == jqiEqual) ? eAnd : eOr; - jsqGetArg(jsq, &elem); - Assert(elem.type == jqiArray); - result->path = path; - result->indirect = indirect; - result->args.items = (ExtractedNode **)palloc((elem.array.nelems + 1) * sizeof(ExtractedNode *)); - result->args.count = 0; - if (jsq->type == jqiContains || jsq->type == jqiOverlap || - jsq->type == jqiContained || jsq->type == jqiEqual) - { - pathItem = (PathItem *)palloc(sizeof(PathItem)); - pathItem->type = iAnyArray; - pathItem->parent = path; - } - else - { - pathItem = path; - } - - if (jsq->type == jqiContained || - (jsq->type == jqiEqual && elem.array.nelems == 0)) - { - ExtractedNode *item = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - - item->hint = e.hint; - item->type = eEmptyArray; - item->path = pathItem->parent; - item->indirect = false; - item->hint = jsq->hint; - - result->args.items[result->args.count] = item; - result->args.count++; - } - - while(jsqIterateArray(&elem, &e)) - { - ExtractedNode *item = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - - item->hint = e.hint; - item->type = eExactValue; - item->path = pathItem; - item->indirect = true; - item->hint = jsq->hint; - - item->exactValue = (JsQueryItem *)palloc(sizeof(JsQueryItem)); - *item->exactValue = e; - result->args.items[result->args.count] = item; - result->args.count++; - } - return result; - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - if (not) - return NULL; - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = eInequality; - result->hint = jsq->hint; - result->path = path; - result->indirect = indirect; - - if (jsq->type == jqiGreater || jsq->type == jqiGreaterOrEqual) - { - result->bounds.leftInclusive = (jsq->type == jqiGreaterOrEqual); - result->bounds.rightBound = NULL; - result->bounds.leftBound = (JsQueryItem *)palloc(sizeof(JsQueryItem)); - jsqGetArg(jsq, result->bounds.leftBound); - } - else - { - result->bounds.rightInclusive = (jsq->type == jqiLessOrEqual); - result->bounds.leftBound = NULL; - result->bounds.rightBound = (JsQueryItem *)palloc(sizeof(JsQueryItem)); - jsqGetArg(jsq, result->bounds.rightBound); - } - return result; - case jqiIs: - if (not) - return NULL; - result = (ExtractedNode *)palloc(sizeof(ExtractedNode)); - result->type = eIs; - result->hint = jsq->hint; - result->path = path; - result->indirect = indirect; - result->isType = jsqGetIsType(jsq); - return result; - case jqiLength: - return NULL; - default: - elog(ERROR,"Wrong state: %d", jsq->type); - } - - return NULL; -} - -/* - * Count number of children connected with nodes of same type. - */ -static int -coundChildren(ExtractedNode *node, ExtractedNodeType type, - bool first, bool *found) -{ - if ((node->indirect || node->type != type) && !first) - { - return 1; - } - else - { - int i, total = 0; - if (!first) - *found = true; - for (i = 0; i < node->args.count; i++) - total += coundChildren(node->args.items[i], type, false, found); - return total; - } -} - -/* - * Fill array of children connected with nodes of same type. - */ -static void -fillChildren(ExtractedNode *node, ExtractedNodeType type, bool first, - ExtractedNode **items, int *i) -{ - if ((node->indirect || node->type != type) && !first) - { - items[*i] = node; - (*i)++; - } - else - { - int j; - for (j = 0; j < node->args.count; j++) - fillChildren(node->args.items[j], type, false, items, i); - } -} - -/* - * Turn tree into "flat" form, turning nested binary AND/OR operators into - * single n-ary AND/OR operators. - */ -static void -flatternTree(ExtractedNode *node) -{ - if (node->type == eAnd || node->type == eOr) - { - int count; - bool found = false; - - count = coundChildren(node, node->type, true, &found); - - if (found) - { - int i = 0; - ExtractedNode **items = (ExtractedNode **)palloc(count * sizeof(ExtractedNode *)); - fillChildren(node, node->type, true, items, &i); - node->args.items = items; - node->args.count = count; - } - } - if (node->type == eAnd || node->type == eOr) - { - int i; - for (i = 0; i < node->args.count; i++) - flatternTree(node->args.items[i]); - } -} - -/* - * Compare path items chains from child to parent. - */ -static int -comparePathItems(PathItem *i1, PathItem *i2) -{ - int cmp; - - if (i1 == i2) - return 0; - - if (!i1) - return -1; - if (!i2) - return 1; - - if (i1->type != i2->type) - { - return (i1->type < i2->type) ? -1 : 1; - } - - if (i1->type == iKey) - cmp = memcmp(i1->s, i2->s, Min(i1->len, i2->len)); - else - cmp = 0; - - if (cmp == 0) - { - if (i1->len != i2->len) - return (i1->len < i2->len) ? -1 : 1; - return comparePathItems(i1->parent, i2->parent); - } - else - { - return cmp; - } -} - -bool -isLogicalNodeType(ExtractedNodeType type) -{ - if (type == eAnd || type == eOr) - return true; - else - return false; -} - -/* - * Compare nodes in the order where conditions to the same fields are located - * together. - */ -static int -compareNodes(const void *a1, const void *a2) -{ - ExtractedNode *n1 = *((ExtractedNode **)a1); - ExtractedNode *n2 = *((ExtractedNode **)a2); - - if (n1->indirect != n2->indirect) - { - if (n1->indirect) - return 1; - if (n2->indirect) - return -1; - } - - if (n1->type != n2->type) - return (n1->type < n2->type) ? -1 : 1; - - if (!isLogicalNodeType(n1->type)) - { - int cmp = comparePathItems(n1->path, n2->path); - if (cmp) return cmp; - } - - if (n1->number != n2->number) - return (n1->number < n2->number) ? -1 : 1; - - return 0; -} - -/* - * Compare json values represented by JsQueryItems. - */ -static int -compareJsQueryItem(JsQueryItem *v1, JsQueryItem *v2) -{ - char *s1, *s2; - int32 len1, len2, cmp; - - if (v1->type != v2->type) - return (v1->type < v2->type) ? -1 : 1; - - switch(v1->type) - { - case jqiNull: - return 0; - case jqiString: - s1 = jsqGetString(v1, &len1); - s2 = jsqGetString(v2, &len2); - cmp = memcmp(s1, s2, Min(len1, len2)); - if (cmp != 0 || len1 == len2) - return cmp; - return (len1 < len2) ? -1 : 1; - case jqiBool: - len1 = jsqGetBool(v1); - len2 = jsqGetBool(v2); - - return (len1 - len2); - case jqiNumeric: - return DatumGetInt32(DirectFunctionCall2(numeric_cmp, - PointerGetDatum(jsqGetNumeric(v1)), - PointerGetDatum(jsqGetNumeric(v2)))); - default: - elog(ERROR, "Wrong state"); - } - - return 0; /* make compiler happy */ -} - -/* - * Process group of nodes representing conditions for the same field. After - * processing group of nodes is replaced with one node. - */ -static void -processGroup(ExtractedNode *node, int start, int end) -{ - int i; - JsQueryItem *leftBound = NULL, - *rightBound = NULL, - *exactValue = NULL; - bool leftInclusive = false, - rightInclusive = false, - first = true; - ExtractedNode *child; - ExtractedNodeType type = eAny; - JsQueryItemType isType = jqiNull; - - if (end - start < 2) - return; - - for (i = start; i < end; i++) - { - int cmp; - - child = node->args.items[i]; - - if (first || child->type <= type) - { - type = child->type; - first = false; - Assert(!isLogicalNodeType(type)); - switch(type) - { - case eAny: - case eEmptyArray: - break; - case eIs: - isType = child->isType; - break; - case eInequality: - if (child->bounds.leftBound) - { - if (!leftBound) - { - leftBound = child->bounds.leftBound; - leftInclusive = child->bounds.leftInclusive; - } - cmp = compareJsQueryItem(child->bounds.leftBound, - leftBound); - if (cmp > 0) - { - leftBound = child->bounds.leftBound; - leftInclusive = child->bounds.leftInclusive; - } - if (cmp == 0 && leftInclusive) - { - leftInclusive = child->bounds.leftInclusive; - } - } - if (child->bounds.rightBound) - { - if (!rightBound) - { - rightBound = child->bounds.rightBound; - rightInclusive = child->bounds.rightInclusive; - } - cmp = compareJsQueryItem(child->bounds.rightBound, - rightBound); - if (cmp > 0) - { - rightBound = child->bounds.rightBound; - rightInclusive = child->bounds.rightInclusive; - } - if (cmp == 0 && rightInclusive) - { - rightInclusive = child->bounds.rightInclusive; - } - } - break; - case eExactValue: - exactValue = child->exactValue; - break; - default: - elog(ERROR, "Wrong state"); - break; - - } - } - } - - child = node->args.items[start]; - child->type = type; - - switch(type) - { - case eAny: - case eEmptyArray: - break; - case eIs: - child->isType = isType; - break; - case eInequality: - child->bounds.leftBound = leftBound; - child->bounds.rightBound = rightBound; - child->bounds.leftInclusive = leftInclusive; - child->bounds.rightInclusive = rightInclusive; - break; - case eExactValue: - child->exactValue = exactValue; - break; - default: - elog(ERROR, "Wrong state"); - break; - } - - for (i = start + 1; i < end; i++) - node->args.items[i] = NULL; -} - -/* - * Reduce number of nodes in tree, by turning multiple conditions about - * same field in same context into one node. - */ -static void -simplifyRecursive(ExtractedNode *node) -{ - if (node->type == eAnd) - { - int i, groupStart = -1; - ExtractedNode *child, *prevChild = NULL; - - for (i = 0; i < node->args.count; i++) - node->args.items[i]->number = i; - - pg_qsort(node->args.items, node->args.count, - sizeof(ExtractedNode *), compareNodes); - - for (i = 0; i < node->args.count; i++) - { - child = node->args.items[i]; - if (child->indirect || isLogicalNodeType(child->type)) - break; - if (!prevChild || comparePathItems(child->path, prevChild->path) != 0) - { - if (groupStart >= 0) - processGroup(node, groupStart, i); - groupStart = i; - } - prevChild = child; - } - if (groupStart >= 0) - processGroup(node, groupStart, i); - } - - if (node->type == eAnd || node->type == eOr) - { - int i; - for (i = 0; i < node->args.count; i++) - { - if (node->args.items[i]) - simplifyRecursive(node->args.items[i]); - } - } -} - -/* - * Get selectivity class of scalar node. - */ -static SelectivityClass -getScalarSelectivityClass(ExtractedNode *node) -{ - Assert(!isLogicalNodeType(node->type)); - switch(node->type) - { - case eAny: - return sAny; - case eIs: - return sIs; - case eInequality: - if (node->bounds.leftBound && node->bounds.rightBound) - return sRange; - else - return sInequal; - case eEmptyArray: - case eExactValue: - return sEqual; - default: - elog(ERROR, "Wrong state"); - return sAny; - } -} - -/* - * Make entries for all leaf tree nodes using user-provided handler. - */ -static ExtractedNode * -makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra) -{ - if (node->type == eAnd || node->type == eOr) - { - int i, j = 0; - ExtractedNode *child; - for (i = 0; i < node->args.count; i++) - { - child = node->args.items[i]; - if (!child) continue; - if (child->sClass > node->sClass && !child->forceIndex) - { - Assert(node->type != eOr); - continue; - } - child = makeEntries(child, handler, extra); - if (child) - { - node->args.items[j] = child; - j++; - } - else if (node->type == eOr) - { - return NULL; - } - } - if (j == 1) - { - return node->args.items[0]; - } - if (j > 0) - { - node->args.count = j; - return node; - } - else - { - return NULL; - } - } - else - { - int entryNum; - - if (node->hint == jsqNoIndex) - return NULL; - - entryNum = handler(node, extra); - if (entryNum >= 0) - { - node->entryNum = entryNum; - return node; - } - else - { - return NULL; - } - } -} - -static void -setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler, - Pointer extra) -{ - int i; - bool first; - ExtractedNode *child; - - switch(node->type) - { - case eAnd: - case eOr: - first = true; - node->forceIndex = false; - for (i = 0; i < node->args.count; i++) - { - child = node->args.items[i]; - - if (!child) - continue; - - if (!isLogicalNodeType(child->type)) - { - if (child->hint == jsqNoIndex || - !checkHandler(child, extra)) - continue; - } - - setSelectivityClass(child, checkHandler, extra); - - if (child->forceIndex) - node->forceIndex = true; - - if (first) - { - node->sClass = child->sClass; - } - else - { - if (node->type == eAnd) - node->sClass = Min(node->sClass, child->sClass); - else - node->sClass = Max(node->sClass, child->sClass); - } - first = false; - } - break; - default: - node->sClass = getScalarSelectivityClass(node); - node->forceIndex = node->hint == jsqForceIndex; - break; - } -} - -/* - * Turn jsquery into tree of entries using user-provided handler. - */ -ExtractedNode * -extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, - CheckEntryHandler checkHandler, Pointer extra) -{ - ExtractedNode *root; - JsQueryItem jsq; - - jsqInit(&jsq, jq); - root = recursiveExtract(&jsq, false, false, NULL); - if (root) - { - flatternTree(root); - simplifyRecursive(root); - setSelectivityClass(root, checkHandler, extra); - root = makeEntries(root, makeHandler, extra); - } - return root; -} - -/* - * Evaluate previously extracted tree. - */ -bool -execRecursive(ExtractedNode *node, bool *check) -{ - int i; - switch(node->type) - { - case eAnd: - for (i = 0; i < node->args.count; i++) - if (!execRecursive(node->args.items[i], check)) - return false; - return true; - case eOr: - for (i = 0; i < node->args.count; i++) - if (execRecursive(node->args.items[i], check)) - return true; - return false; - default: - return check[node->entryNum]; - } -} - -/* - * Evaluate previously extracted tree using tri-state logic. - */ -bool -execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check) -{ - GinTernaryValue res, v; - int i; - - switch(node->type) - { - case eAnd: - res = GIN_TRUE; - for (i = 0; i < node->args.count; i++) - { - v = execRecursive(node->args.items[i], check); - if (v == GIN_FALSE) - return GIN_FALSE; - else if (v == GIN_MAYBE) - res = GIN_MAYBE; - } - return res; - case eOr: - res = GIN_FALSE; - for (i = 0; i < node->args.count; i++) - { - v = execRecursive(node->args.items[i], check); - if (v == GIN_TRUE) - return GIN_TRUE; - else if (v == GIN_MAYBE) - res = GIN_MAYBE; - } - return res; - default: - return check[node->entryNum]; - } -} - -/* - * Debug print of variable path. - */ -static void -debugPath(StringInfo buf, PathItem *path) -{ - if (path->parent) - { - debugPath(buf, path->parent); - appendStringInfo(buf, "."); - } - switch (path->type) - { - case jqiAny: - appendStringInfoChar(buf, '*'); - break; - case jqiAnyKey: - appendStringInfoChar(buf, '%'); - break; - case jqiAnyArray: - appendStringInfoChar(buf, '#'); - break; - case jqiIndexArray: - appendStringInfo(buf, "#%d", path->arrayIndex); - break; - case jqiKey: - appendBinaryStringInfo(buf, path->s, path->len); - break; - } -} - -/* - * Debug print of jsquery value. - */ -static void -debugValue(StringInfo buf, JsQueryItem *v) -{ - char *s; - int len; - - switch(v->type) - { - case jqiNull: - appendStringInfo(buf, "null"); - break; - case jqiString: - s = jsqGetString(v, &len); - appendStringInfo(buf, "\""); - appendBinaryStringInfo(buf, s, len); - appendStringInfo(buf, "\""); - break; - case jqiBool: - appendStringInfo(buf, jsqGetBool(v) ? "true" : "false"); - break; - case jqiNumeric: - s = DatumGetCString(DirectFunctionCall1(numeric_out, - PointerGetDatum(jsqGetNumeric(v)))); - appendStringInfoString(buf, s); - break; - default: - elog(ERROR,"Wrong type"); - break; - } -} - -static const char * -getTypeString(int32 type) -{ - switch (type) - { - case jbvArray: - return "array"; - case jbvObject: - return "object"; - case jbvString: - return "string"; - case jbvNumeric: - return "numeric"; - case jbvBool: - return "boolean"; - case jbvNull: - return "null"; - default: - elog(ERROR,"Wrong type"); - return NULL; - } -} - - -/* - * Recursive worker of debug print of query processing. - */ -static void -debugRecursive(StringInfo buf, ExtractedNode *node, int shift) -{ - int i; - - appendStringInfoSpaces(buf, shift * 2); - - if (isLogicalNodeType(node->type)) - { - appendStringInfo(buf, (node->type == eAnd) ? "AND\n" : "OR\n"); - for (i = 0; i < node->args.count; i++) - debugRecursive(buf, node->args.items[i], shift + 1); - return; - } - - debugPath(buf, node->path); - switch(node->type) - { - case eExactValue: - appendStringInfo(buf, " = "); - debugValue(buf, node->exactValue); - appendStringInfo(buf, " ,"); - break; - case eAny: - appendStringInfo(buf, " = * ,"); - break; - case eEmptyArray: - appendStringInfo(buf, " = [] ,"); - break; - case eIs: - appendStringInfo(buf, " IS %s ,", getTypeString(node->isType)); - break; - case eInequality: - if (node->bounds.leftBound) - { - if (node->bounds.leftInclusive) - appendStringInfo(buf, " >= "); - else - appendStringInfo(buf, " > "); - debugValue(buf, node->bounds.leftBound); - appendStringInfo(buf, " ,"); - } - if (node->bounds.rightBound) - { - if (node->bounds.rightInclusive) - appendStringInfo(buf, " <= "); - else - appendStringInfo(buf, " < "); - debugValue(buf, node->bounds.rightBound); - appendStringInfo(buf, " ,"); - } - break; - default: - elog(ERROR,"Wrong type"); - break; - } - appendStringInfo(buf, " entry %d \n", node->entryNum); -} - -/* - * Debug print of query processing. - */ -char * -debugJsQuery(JsQuery *jq, MakeEntryHandler makeHandler, - CheckEntryHandler checkHandler, Pointer extra) -{ - ExtractedNode *root; - StringInfoData buf; - - root = extractJsQuery(jq, makeHandler, checkHandler, extra); - if (!root) - return "NULL\n"; - - initStringInfo(&buf); - debugRecursive(&buf, root, 0); - appendStringInfoChar(&buf, '\0'); - return buf.data; -} diff --git a/jsquery/jsquery_gram.y b/jsquery/jsquery_gram.y deleted file mode 100644 index 7db9a2ded5..0000000000 --- a/jsquery/jsquery_gram.y +++ /dev/null @@ -1,364 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_gram.y - * Grammar definitions for jsquery datatype - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_gram.y - * - *------------------------------------------------------------------------- - */ - -%{ -#include "postgres.h" - -#include "fmgr.h" -#include "utils/builtins.h" - -#include "jsquery.h" - -/* - * Bison doesn't allocate anything that needs to live across parser calls, - * so we can easily have it use palloc instead of malloc. This prevents - * memory leaks if we error out during parsing. Note this only works with - * bison >= 2.0. However, in bison 1.875 the default is to use alloca() - * if possible, so there's not really much problem anyhow, at least if - * you're building with gcc. - */ -#define YYMALLOC palloc -#define YYFREE pfree - -/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ -#undef fprintf -#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg) - -static void -fprintf_to_ereport(const char *fmt, const char *msg) -{ - ereport(ERROR, (errmsg_internal("%s", msg))); -} - -/* struct string is shared between scan and gram */ -typedef struct string { - char *val; - int len; - int total; -} string; -#include - -/* flex 2.5.4 doesn't bother with a decl for this */ -int jsquery_yylex(YYSTYPE * yylval_param); -void jsquery_yyerror(JsQueryParseItem **result, const char *message); - -static JsQueryParseItem* -makeItemType(int type) -{ - JsQueryParseItem* v = palloc(sizeof(*v)); - - v->type = type; - v->hint = jsqIndexDefault; - v->next = NULL; - - return v; -} - -static JsQueryParseItem* -makeIndexArray(string *s) -{ - JsQueryParseItem* v = makeItemType(jqiIndexArray); - - v->arrayIndex = pg_atoi(s->val, 4, 0); - - return v; -} - -static JsQueryParseItem* -makeItemString(string *s) -{ - JsQueryParseItem *v; - - if (s == NULL) - { - v = makeItemType(jqiNull); - } - else - { - v = makeItemType(jqiString); - v->string.val = s->val; - v->string.len = s->len; - } - - return v; -} - -static JsQueryParseItem* -makeItemKey(string *s) -{ - JsQueryParseItem *v; - - v = makeItemString(s); - v->type = jqiKey; - - return v; -} - -static JsQueryParseItem* -makeItemNumeric(string *s) -{ - JsQueryParseItem *v; - - v = makeItemType(jqiNumeric); - v->numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(s->val), 0, -1)); - - return v; -} - -static JsQueryParseItem* -makeItemBool(bool val) { - JsQueryParseItem *v = makeItemType(jqiBool); - - v->boolean = val; - - return v; -} - -static JsQueryParseItem* -makeItemArray(List *list) -{ - JsQueryParseItem *v = makeItemType(jqiArray); - - v->array.nelems = list_length(list); - - if (v->array.nelems > 0) - { - ListCell *cell; - int i = 0; - - v->array.elems = palloc(sizeof(JsQueryParseItem) * v->array.nelems); - - foreach(cell, list) - v->array.elems[i++] = (JsQueryParseItem*)lfirst(cell); - } - else - { - v->array.elems = NULL; - } - - return v; -} - -static JsQueryParseItem* -makeItemBinary(int type, JsQueryParseItem* la, JsQueryParseItem *ra) -{ - JsQueryParseItem *v = makeItemType(type); - - v->args.left = la; - v->args.right = ra; - - return v; -} - -static JsQueryParseItem* -makeItemUnary(int type, JsQueryParseItem* a) -{ - JsQueryParseItem *v = makeItemType(type); - - v->arg = a; - - return v; -} - -static JsQueryParseItem* -makeItemIs(int isType) -{ - JsQueryParseItem *v = makeItemType(jqiIs); - - v->isType = isType; - - return v; -} - -static JsQueryParseItem* -makeItemList(List *list) { - JsQueryParseItem *head, *end; - ListCell *cell; - - head = end = (JsQueryParseItem*)linitial(list); - - foreach(cell, list) - { - JsQueryParseItem *c = (JsQueryParseItem*)lfirst(cell); - - if (c == head) - continue; - - end->next = c; - end = c; - } - - return head; -} - -%} - -/* BISON Declarations */ -%pure-parser -%expect 0 -%name-prefix="jsquery_yy" -%error-verbose -%parse-param {JsQueryParseItem **result} - -%union { - string str; - List *elems; /* list of JsQueryParseItem */ - - JsQueryParseItem *value; - JsQueryHint hint; -} - -%token IN_P IS_P OR_P AND_P NOT_P NULL_P TRUE_P - ARRAY_T FALSE_P NUMERIC_T OBJECT_T - STRING_T BOOLEAN_T - -%token STRING_P NUMERIC_P INT_P - -%type result scalar_value - -%type path value_list - -%type key key_any right_expr expr array numeric - -%token HINT_P - -%left OR_P -%left AND_P -%right NOT_P -%nonassoc IN_P IS_P -%nonassoc '(' ')' - -/* Grammar follows */ -%% - -result: - expr { *result = $1; } - | /* EMPTY */ { *result = NULL; } - ; - -array: - '[' value_list ']' { $$ = makeItemArray($2); } - ; - -scalar_value: - STRING_P { $$ = makeItemString(&$1); } - | IN_P { $$ = makeItemString(&$1); } - | IS_P { $$ = makeItemString(&$1); } - | OR_P { $$ = makeItemString(&$1); } - | AND_P { $$ = makeItemString(&$1); } - | NOT_P { $$ = makeItemString(&$1); } - | NULL_P { $$ = makeItemString(NULL); } - | TRUE_P { $$ = makeItemBool(true); } - | ARRAY_T { $$ = makeItemString(&$1); } - | FALSE_P { $$ = makeItemBool(false); } - | NUMERIC_T { $$ = makeItemString(&$1); } - | OBJECT_T { $$ = makeItemString(&$1); } - | STRING_T { $$ = makeItemString(&$1); } - | BOOLEAN_T { $$ = makeItemString(&$1); } - | NUMERIC_P { $$ = makeItemNumeric(&$1); } - | INT_P { $$ = makeItemNumeric(&$1); } - ; - -value_list: - scalar_value { $$ = lappend(NIL, $1); } - | value_list ',' scalar_value { $$ = lappend($1, $3); } - ; - -numeric: - NUMERIC_P { $$ = makeItemNumeric(&$1); } - | INT_P { $$ = makeItemNumeric(&$1); } - ; - -right_expr: - '=' scalar_value { $$ = makeItemUnary(jqiEqual, $2); } - | IN_P '(' value_list ')' { $$ = makeItemUnary(jqiIn, makeItemArray($3)); } - | '=' array { $$ = makeItemUnary(jqiEqual, $2); } - | '=' '*' { $$ = makeItemUnary(jqiEqual, makeItemType(jqiAny)); } - | '<' numeric { $$ = makeItemUnary(jqiLess, $2); } - | '>' numeric { $$ = makeItemUnary(jqiGreater, $2); } - | '<' '=' numeric { $$ = makeItemUnary(jqiLessOrEqual, $3); } - | '>' '=' numeric { $$ = makeItemUnary(jqiGreaterOrEqual, $3); } - | '@' '>' array { $$ = makeItemUnary(jqiContains, $3); } - | '<' '@' array { $$ = makeItemUnary(jqiContained, $3); } - | '&' '&' array { $$ = makeItemUnary(jqiOverlap, $3); } - | IS_P ARRAY_T { $$ = makeItemIs(jbvArray); } - | IS_P NUMERIC_T { $$ = makeItemIs(jbvNumeric); } - | IS_P OBJECT_T { $$ = makeItemIs(jbvObject); } - | IS_P STRING_T { $$ = makeItemIs(jbvString); } - | IS_P BOOLEAN_T { $$ = makeItemIs(jbvBool); } - ; - -expr: - path right_expr { $$ = makeItemList(lappend($1, $2)); } - | path HINT_P right_expr { $3->hint = $2; $$ = makeItemList(lappend($1, $3)); } - | NOT_P expr { $$ = makeItemUnary(jqiNot, $2); } - /* - * In next two lines NOT_P is a path actually, not a an - * logical expression. - */ - | NOT_P HINT_P right_expr { $3->hint = $2; $$ = makeItemList(lappend(lappend(NIL, makeItemKey(&$1)), $3)); } - | NOT_P right_expr { $$ = makeItemList(lappend(lappend(NIL, makeItemKey(&$1)), $2)); } - | path '(' expr ')' { $$ = makeItemList(lappend($1, $3)); } - | '(' expr ')' { $$ = $2; } - | expr AND_P expr { $$ = makeItemBinary(jqiAnd, $1, $3); } - | expr OR_P expr { $$ = makeItemBinary(jqiOr, $1, $3); } - ; - -/* - * key is always a string, not a bool or numeric - */ -key: - '*' { $$ = makeItemType(jqiAny); } - | '#' { $$ = makeItemType(jqiAnyArray); } - | '%' { $$ = makeItemType(jqiAnyKey); } - | '*' ':' { $$ = makeItemType(jqiAll); } - | '#' ':' { $$ = makeItemType(jqiAllArray); } - | '%' ':' { $$ = makeItemType(jqiAllKey); } - | '$' { $$ = makeItemType(jqiCurrent); } - | '@' '#' { $$ = makeItemType(jqiLength); } - | '#' INT_P { $$ = makeIndexArray(&$2); } - | STRING_P { $$ = makeItemKey(&$1); } - | IN_P { $$ = makeItemKey(&$1); } - | IS_P { $$ = makeItemKey(&$1); } - | OR_P { $$ = makeItemKey(&$1); } - | AND_P { $$ = makeItemKey(&$1); } - | NULL_P { $$ = makeItemKey(&$1); } - | TRUE_P { $$ = makeItemKey(&$1); } - | ARRAY_T { $$ = makeItemKey(&$1); } - | FALSE_P { $$ = makeItemKey(&$1); } - | NUMERIC_T { $$ = makeItemKey(&$1); } - | OBJECT_T { $$ = makeItemKey(&$1); } - | STRING_T { $$ = makeItemKey(&$1); } - | BOOLEAN_T { $$ = makeItemKey(&$1); } - | NUMERIC_P { $$ = makeItemKey(&$1); } - | INT_P { $$ = makeItemKey(&$1); } - ; - -/* - * NOT keyword needs separate processing - */ -key_any: - key { $$ = $$; } - | NOT_P { $$ = makeItemKey(&$1); } - ; - -path: - key { $$ = lappend(NIL, $1); } - | path '.' key_any { $$ = lappend($1, $3); } - | NOT_P '.' key_any { $$ = lappend(lappend(NIL, makeItemKey(&$1)), $3); } - ; - -%% - -#include "jsquery_scan.c" diff --git a/jsquery/jsquery_io.c b/jsquery/jsquery_io.c deleted file mode 100644 index a295244e75..0000000000 --- a/jsquery/jsquery_io.c +++ /dev/null @@ -1,403 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_io.c - * I/O functions for jsquery datatype - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_io.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" -#include "miscadmin.h" -#include "lib/stringinfo.h" -#include "utils/builtins.h" -#include "utils/json.h" - -#include "jsquery.h" - -PG_MODULE_MAGIC; - -static int -flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrentInPath) -{ - int32 pos = buf->len - VARHDRSZ; /* position from begining of jsquery data */ - int32 chld, next; - - check_stack_depth(); - - Assert((item->type & item->hint) == 0); - Assert((item->type & JSQ_HINT_MASK) == 0); - - appendStringInfoChar(buf, (char)(item->type | item->hint)); - alignStringInfoInt(buf); - - next = (item->next) ? buf->len : 0; - appendBinaryStringInfo(buf, (char*)&next /* fake value */, sizeof(next)); - - switch(item->type) - { - case jqiKey: - if (onlyCurrentInPath) - elog(ERROR,"Array length should be last in path"); - case jqiString: - appendBinaryStringInfo(buf, (char*)&item->string.len, sizeof(item->string.len)); - appendBinaryStringInfo(buf, item->string.val, item->string.len); - appendStringInfoChar(buf, '\0'); - break; - case jqiNumeric: - appendBinaryStringInfo(buf, (char*)item->numeric, VARSIZE(item->numeric)); - break; - case jqiBool: - appendBinaryStringInfo(buf, (char*)&item->boolean, sizeof(item->boolean)); - break; - case jqiIs: - appendBinaryStringInfo(buf, (char*)&item->isType, sizeof(item->isType)); - break; - case jqiArray: - { - int32 i, arrayStart; - - appendBinaryStringInfo(buf, (char*)&item->array.nelems, sizeof(item->array.nelems)); - arrayStart = buf->len; - - /* reserve place for "pointers" to array's elements */ - for(i=0; iarray.nelems; i++) - appendBinaryStringInfo(buf, (char*)&i /* fake value */, sizeof(i)); - - for(i=0; iarray.nelems; i++) - { - chld = flattenJsQueryParseItem(buf, item->array.elems[i], onlyCurrentInPath); - *(int32*)(buf->data + arrayStart + i * sizeof(i)) = chld; - } - - } - break; - case jqiAnd: - case jqiOr: - { - int32 left, right; - - left = buf->len; - appendBinaryStringInfo(buf, (char*)&left /* fake value */, sizeof(left)); - right = buf->len; - appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right)); - - chld = flattenJsQueryParseItem(buf, item->args.left, onlyCurrentInPath); - *(int32*)(buf->data + left) = chld; - chld = flattenJsQueryParseItem(buf, item->args.right, onlyCurrentInPath); - *(int32*)(buf->data + right) = chld; - } - break; - case jqiEqual: - case jqiIn: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - case jqiNot: - { - int32 arg; - - arg = buf->len; - appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg)); - - chld = flattenJsQueryParseItem(buf, item->arg, onlyCurrentInPath); - *(int32*)(buf->data + arg) = chld; - } - break; - case jqiIndexArray: - appendBinaryStringInfo(buf, (char*)&item->arrayIndex, - sizeof(item->arrayIndex)); - case jqiAny: - case jqiAnyArray: - case jqiAnyKey: - case jqiAll: - case jqiAllArray: - case jqiAllKey: - if (onlyCurrentInPath) - elog(ERROR,"Array length should be last in path"); - case jqiCurrent: - case jqiNull: - break; - case jqiLength: - onlyCurrentInPath = true; - break; - default: - elog(ERROR, "Unknown type: %d", item->type); - } - - if (item->next) - { - chld = flattenJsQueryParseItem(buf, item->next, onlyCurrentInPath); - *(int32*)(buf->data + next) = chld; - } - - return pos; -} - -PG_FUNCTION_INFO_V1(jsquery_in); -Datum -jsquery_in(PG_FUNCTION_ARGS) -{ - char *in = PG_GETARG_CSTRING(0); - int32 len = strlen(in); - JsQueryParseItem *jsquery = parsejsquery(in, len); - JsQuery *res; - StringInfoData buf; - - initStringInfo(&buf); - enlargeStringInfo(&buf, 4 * len /* estimation */); - - appendStringInfoSpaces(&buf, VARHDRSZ); - - if (jsquery != NULL) - { - flattenJsQueryParseItem(&buf, jsquery, false); - - res = (JsQuery*)buf.data; - SET_VARSIZE(res, buf.len); - - PG_RETURN_JSQUERY(res); - } - - PG_RETURN_NULL(); -} - -static void -printHint(StringInfo buf, JsQueryHint hint) -{ - switch(hint) - { - case jsqForceIndex: - appendStringInfoString(buf, " /*-- index */ "); - break; - case jsqNoIndex: - appendStringInfoString(buf, " /*-- noindex */ "); - break; - case jsqIndexDefault: - break; - default: - elog(ERROR, "Unknown hint: %d", hint); - } -} - -static void -printOperation(StringInfo buf, JsQueryItemType type) -{ - switch(type) - { - case jqiAnd: - appendBinaryStringInfo(buf, " AND ", 5); break; - case jqiOr: - appendBinaryStringInfo(buf, " OR ", 4); break; - case jqiEqual: - appendBinaryStringInfo(buf, " = ", 3); break; - case jqiLess: - appendBinaryStringInfo(buf, " < ", 3); break; - case jqiGreater: - appendBinaryStringInfo(buf, " > ", 3); break; - case jqiLessOrEqual: - appendBinaryStringInfo(buf, " <= ", 4); break; - case jqiGreaterOrEqual: - appendBinaryStringInfo(buf, " >= ", 4); break; - case jqiContains: - appendBinaryStringInfo(buf, " @> ", 4); break; - case jqiContained: - appendBinaryStringInfo(buf, " <@ ", 4); break; - case jqiOverlap: - appendBinaryStringInfo(buf, " && ", 4); break; - default: - elog(ERROR, "Unknown type: %d", type); - } -} - -static void -printJsQueryItem(StringInfo buf, JsQueryItem *v, bool inKey, bool printBracketes) -{ - JsQueryItem elem; - bool first = true; - - check_stack_depth(); - - printHint(buf, v->hint); - - switch(v->type) - { - case jqiNull: - appendStringInfoString(buf, "null"); - break; - case jqiKey: - if (inKey) - appendStringInfoChar(buf, '.'); - /* follow next */ - case jqiString: - escape_json(buf, jsqGetString(v, NULL)); - break; - case jqiNumeric: - appendStringInfoString(buf, - DatumGetCString(DirectFunctionCall1(numeric_out, - PointerGetDatum(jsqGetNumeric(v))))); - break; - case jqiBool: - if (jsqGetBool(v)) - appendBinaryStringInfo(buf, "true", 4); - else - appendBinaryStringInfo(buf, "false", 5); - break; - case jqiIs: - appendBinaryStringInfo(buf, " IS ", 4); - switch(jsqGetIsType(v)) - { - case jbvString: - appendBinaryStringInfo(buf, "STRING", 6); - break; - case jbvNumeric: - appendBinaryStringInfo(buf, "NUMERIC", 7); - break; - case jbvBool: - appendBinaryStringInfo(buf, "BOOLEAN", 7); - break; - case jbvArray: - appendBinaryStringInfo(buf, "ARRAY", 5); - break; - case jbvObject: - appendBinaryStringInfo(buf, "OBJECT", 6); - break; - default: - elog(ERROR, "Unknown type for IS: %d", jsqGetIsType(v)); - break; - } - break; - case jqiArray: - if (printBracketes) - appendStringInfoChar(buf, '['); - - while(jsqIterateArray(v, &elem)) - { - if (first == false) - appendBinaryStringInfo(buf, ", ", 2); - else - first = false; - printJsQueryItem(buf, &elem, false, true); - } - - if (printBracketes) - appendStringInfoChar(buf, ']'); - break; - case jqiAnd: - case jqiOr: - appendStringInfoChar(buf, '('); - jsqGetLeftArg(v, &elem); - printJsQueryItem(buf, &elem, false, true); - printOperation(buf, v->type); - jsqGetRightArg(v, &elem); - printJsQueryItem(buf, &elem, false, true); - appendStringInfoChar(buf, ')'); - break; - case jqiEqual: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - printOperation(buf, v->type); - jsqGetArg(v, &elem); - printJsQueryItem(buf, &elem, false, true); - break; - case jqiIn: - appendBinaryStringInfo(buf, " IN (", 5); - jsqGetArg(v, &elem); - printJsQueryItem(buf, &elem, false, false); - appendStringInfoChar(buf, ')'); - break; - case jqiNot: - appendBinaryStringInfo(buf, "(NOT ", 5); - jsqGetArg(v, &elem); - printJsQueryItem(buf, &elem, false, true); - appendStringInfoChar(buf, ')'); - break; - case jqiCurrent: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '$'); - break; - case jqiLength: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '@'); - appendStringInfoChar(buf, '#'); - break; - case jqiAny: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '*'); - break; - case jqiAnyArray: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '#'); - break; - case jqiAnyKey: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '%'); - break; - case jqiAll: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '*'); - appendStringInfoChar(buf, ':'); - break; - case jqiAllArray: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '#'); - appendStringInfoChar(buf, ':'); - break; - case jqiAllKey: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfoChar(buf, '%'); - appendStringInfoChar(buf, ':'); - break; - case jqiIndexArray: - if (inKey) - appendStringInfoChar(buf, '.'); - appendStringInfo(buf, "#%u", v->arrayIndex); - break; - default: - elog(ERROR, "Unknown JsQueryItem type: %d", v->type); - } - - if (jsqGetNext(v, &elem)) - printJsQueryItem(buf, &elem, true, true); -} - -PG_FUNCTION_INFO_V1(jsquery_out); -Datum -jsquery_out(PG_FUNCTION_ARGS) -{ - JsQuery *in = PG_GETARG_JSQUERY(0); - StringInfoData buf; - JsQueryItem v; - - initStringInfo(&buf); - enlargeStringInfo(&buf, VARSIZE(in) /* estimation */); - - jsqInit(&v, in); - printJsQueryItem(&buf, &v, false, true); - - PG_RETURN_CSTRING(buf.data); -} - - diff --git a/jsquery/jsquery_op.c b/jsquery/jsquery_op.c deleted file mode 100644 index a6c8864938..0000000000 --- a/jsquery/jsquery_op.c +++ /dev/null @@ -1,1009 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_op.c - * Functions and operations over jsquery/jsonb datatypes - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_op.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "miscadmin.h" -#include "utils/builtins.h" -#include "utils/pg_crc.h" -#if PG_VERSION_NUM >= 90500 -/* - * We have to keep same checksum algorithm as in pre-9.5 in order to be - * pg_upgradeable. - */ -#define INIT_CRC32 INIT_LEGACY_CRC32 -#define FIN_CRC32 FIN_LEGACY_CRC32 -#define COMP_CRC32 COMP_LEGACY_CRC32 -#endif - -#include "jsquery.h" - -static bool recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg); - -static int -compareNumeric(Numeric a, Numeric b) -{ - return DatumGetInt32( - DirectFunctionCall2( - numeric_cmp, - PointerGetDatum(a), - PointerGetDatum(b) - ) - ); -} - -#define jbvScalar jbvBinary -static int -JsonbType(JsonbValue *jb) -{ - int type = jb->type; - - if (jb->type == jbvBinary) - { - JsonbContainer *jbc = jb->val.binary.data; - - if (jbc->header & JB_FSCALAR) - type = jbvScalar; - else if (jbc->header & JB_FOBJECT) - type = jbvObject; - else if (jbc->header & JB_FARRAY) - type = jbvArray; - else - elog(ERROR, "Unknown container type: 0x%08x", jbc->header); - } - - return type; -} - -static bool -recursiveAny(JsQueryItem *jsq, JsonbValue *jb) -{ - bool res = false; - JsonbIterator *it; - int32 r; - JsonbValue v; - - check_stack_depth(); - - it = JsonbIteratorInit(jb->val.binary.data); - - while(res == false && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_KEY) - { - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_VALUE); - } - - if (r == WJB_VALUE || r == WJB_ELEM) - { - res = recursiveExecute(jsq, &v, NULL); - - if (res == false && v.type == jbvBinary) - res = recursiveAny(jsq, &v); - } - } - - return res; -} - -static bool -recursiveAll(JsQueryItem *jsq, JsonbValue *jb) -{ - bool res = true; - JsonbIterator *it; - int32 r; - JsonbValue v; - - check_stack_depth(); - - it = JsonbIteratorInit(jb->val.binary.data); - - while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_KEY) - { - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_VALUE); - } - - if (r == WJB_VALUE || r == WJB_ELEM) - { - if ((res = recursiveExecute(jsq, &v, NULL)) == true) - { - if (v.type == jbvBinary) - res = recursiveAll(jsq, &v); - } - - if (res == false) - break; - } - } - - return res; -} - -static bool -checkScalarEquality(JsQueryItem *jsq, JsonbValue *jb) -{ - int len; - char *s; - - if (jsq->type == jqiAny) - return true; - - if (jb->type == jbvBinary) - return false; - - if ((int)jb->type != (int)jsq->type /* see enums */) - return false; - - switch(jsq->type) - { - case jqiNull: - return true; - case jqiString: - s = jsqGetString(jsq, &len); - return (len == jb->val.string.len && memcmp(jb->val.string.val, s, len) == 0); - case jqiBool: - return (jb->val.boolean == jsqGetBool(jsq)); - case jqiNumeric: - return (compareNumeric(jsqGetNumeric(jsq), jb->val.numeric) == 0); - default: - elog(ERROR,"Wrong state"); - } - - return false; -} - -static bool -checkArrayEquality(JsQueryItem *jsq, JsonbValue *jb) -{ - int32 r; - JsonbIterator *it; - JsonbValue v; - JsQueryItem elem; - - if (!(jsq->type == jqiArray && JsonbType(jb) == jbvArray)) - return false; - - - it = JsonbIteratorInit(jb->val.binary.data); - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_BEGIN_ARRAY); - - if (v.val.array.nElems != jsq->array.nelems) - return false; - - while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r != WJB_ELEM) - continue; - - jsqIterateArray(jsq, &elem); - - if (checkScalarEquality(&elem, &v) == false) - return false; - } - - return true; -} - -static bool -checkScalarIn(JsQueryItem *jsq, JsonbValue *jb) -{ - JsQueryItem elem; - - if (jb->type == jbvBinary) - return false; - - if (jsq->type != jqiArray) - return false; - - while(jsqIterateArray(jsq, &elem)) - if (checkScalarEquality(&elem, jb)) - return true; - - return false; -} - -static bool -executeArrayOp(JsQueryItem *jsq, int32 op, JsonbValue *jb) -{ - int32 r = 0; /* keep static analyzer quiet */ - JsonbIterator *it; - JsonbValue v; - JsQueryItem elem; - - if (JsonbType(jb) != jbvArray) - return false; - if (jsq->type != jqiArray) - return false; - - if (op == jqiContains) - { - while(jsqIterateArray(jsq, &elem)) - { - bool res = false; - - it = JsonbIteratorInit(jb->val.binary.data); - - while(res == false && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_ELEM && checkScalarEquality(&elem, &v)) - res = true; - } - - if (res == false) - return false; - } - } - else - { - it = JsonbIteratorInit(jb->val.binary.data); - - while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_ELEM) - { - bool res = false; - - jsqIterateInit(jsq); - while(jsqIterateArray(jsq, &elem)) - { - if (checkScalarEquality(&elem, &v)) - { - if (op == jqiOverlap) - return true; - res = true; - break; - } - } - - if (op == jqiContained && res == false) - return false; - } - } - - if (op == jqiOverlap) - return false; - } - - return true; -} - -static bool -makeCompare(JsQueryItem *jsq, int32 op, JsonbValue *jb) -{ - int res; - - if (jb->type != jbvNumeric) - return false; - if (jsq->type != jqiNumeric) - return false; - - res = compareNumeric(jb->val.numeric, jsqGetNumeric(jsq)); - - switch(op) - { - case jqiEqual: - return (res == 0); - case jqiLess: - return (res < 0); - case jqiGreater: - return (res > 0); - case jqiLessOrEqual: - return (res <= 0); - case jqiGreaterOrEqual: - return (res >= 0); - default: - elog(ERROR, "Unknown operation"); - } - - return false; -} - -static bool -executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg) -{ - bool res = false; - /* - * read arg type - */ - Assert(jsqGetNext(jsq, NULL) == false); - Assert(jsq->type == jqiAny || jsq->type == jqiString || jsq->type == jqiNumeric || - jsq->type == jqiNull || jsq->type == jqiBool || jsq->type == jqiArray); - - if (jsqLeftArg && jsqLeftArg->type == jqiLength) - { - if (JsonbType(jb) == jbvArray || JsonbType(jb) == jbvObject) - { - int32 length; - JsonbIterator *it; - JsonbValue v; - int r; - - it = JsonbIteratorInit(jb->val.binary.data); - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT); - - length = (r == WJB_BEGIN_ARRAY) ? v.val.array.nElems : v.val.object.nPairs; - - v.type = jbvNumeric; - v.val.numeric = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(length))); - - switch(op) - { - case jqiEqual: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - res = makeCompare(jsq, op, &v); - break; - case jqiIn: - res = checkScalarIn(jsq, &v); - break; - case jqiOverlap: - case jqiContains: - case jqiContained: - break; - default: - elog(ERROR, "Unknown operation"); - } - } - } - else - { - switch(op) - { - case jqiEqual: - if (JsonbType(jb) == jbvArray && jsq->type == jqiArray) - res = checkArrayEquality(jsq, jb); - else - res = checkScalarEquality(jsq, jb); - break; - case jqiIn: - res = checkScalarIn(jsq, jb); - break; - case jqiOverlap: - case jqiContains: - case jqiContained: - res = executeArrayOp(jsq, op, jb); - break; - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - res = makeCompare(jsq, op, jb); - break; - default: - elog(ERROR, "Unknown operation"); - } - } - - return res; -} - -static bool -recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg) -{ - JsQueryItem elem; - bool res = false; - - check_stack_depth(); - - switch(jsq->type) { - case jqiAnd: - jsqGetLeftArg(jsq, &elem); - res = recursiveExecute(&elem, jb, jsqLeftArg); - if (res == true) - { - jsqGetRightArg(jsq, &elem); - res = recursiveExecute(&elem, jb, jsqLeftArg); - } - break; - case jqiOr: - jsqGetLeftArg(jsq, &elem); - res = recursiveExecute(&elem, jb, jsqLeftArg); - if (res == false) - { - jsqGetRightArg(jsq, &elem); - res = recursiveExecute(&elem, jb, jsqLeftArg); - } - break; - case jqiNot: - jsqGetArg(jsq, &elem); - res = !recursiveExecute(&elem, jb, jsqLeftArg); - break; - case jqiKey: - if (JsonbType(jb) == jbvObject) { - JsonbValue *v, key; - - key.type = jbvString; - key.val.string.val = jsqGetString(jsq, &key.val.string.len); - - v = findJsonbValueFromContainer(jb->val.binary.data, JB_FOBJECT, &key); - - if (v != NULL) - { - jsqGetNext(jsq, &elem); - res = recursiveExecute(&elem, v, NULL); - pfree(v); - } - } - break; - case jqiCurrent: - jsqGetNext(jsq, &elem); - if (JsonbType(jb) == jbvScalar) - { - JsonbIterator *it; - int32 r; - JsonbValue v; - - it = JsonbIteratorInit(jb->val.binary.data); - - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_BEGIN_ARRAY); - Assert(v.val.array.rawScalar == 1); - Assert(v.val.array.nElems == 1); - - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_ELEM); - - res = recursiveExecute(&elem, &v, jsqLeftArg); - } - else - { - res = recursiveExecute(&elem, jb, jsqLeftArg); - } - break; - case jqiAny: - jsqGetNext(jsq, &elem); - if (recursiveExecute(&elem, jb, NULL)) - res = true; - else if (jb->type == jbvBinary) - res = recursiveAny(&elem, jb); - break; - case jqiAll: - jsqGetNext(jsq, &elem); - if ((res = recursiveExecute(&elem, jb, NULL)) == true) - { - if (jb->type == jbvBinary) - res = recursiveAll(&elem, jb); - } - break; - case jqiAnyArray: - case jqiAllArray: - if (JsonbType(jb) == jbvArray) - { - JsonbIterator *it; - int32 r; - JsonbValue v; - - jsqGetNext(jsq, &elem); - it = JsonbIteratorInit(jb->val.binary.data); - - if (jsq->type == jqiAllArray) - res = true; - - while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_ELEM) - { - res = recursiveExecute(&elem, &v, NULL); - - if (jsq->type == jqiAnyArray) - { - if (res == true) - break; - } - else if (jsq->type == jqiAllArray) - { - if (res == false) - break; - } - } - } - } - break; - case jqiIndexArray: - if (JsonbType(jb) == jbvArray) - { - JsonbValue *v; - - jsqGetNext(jsq, &elem); - - v = getIthJsonbValueFromContainer(jb->val.binary.data, - jsq->arrayIndex); - - res = v && recursiveExecute(&elem, v, NULL); - } - break; - case jqiAnyKey: - case jqiAllKey: - if (JsonbType(jb) == jbvObject) - { - JsonbIterator *it; - int32 r; - JsonbValue v; - - jsqGetNext(jsq, &elem); - it = JsonbIteratorInit(jb->val.binary.data); - - if (jsq->type == jqiAllKey) - res = true; - - while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE) - { - if (r == WJB_VALUE) - { - res = recursiveExecute(&elem, &v, NULL); - - if (jsq->type == jqiAnyKey) - { - if (res == true) - break; - } - else if (jsq->type == jqiAllKey) - { - if (res == false) - break; - } - } - } - } - break; - case jqiEqual: - case jqiIn: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - jsqGetArg(jsq, &elem); - res = executeExpr(&elem, jsq->type, jb, jsqLeftArg); - break; - case jqiLength: - jsqGetNext(jsq, &elem); - res = recursiveExecute(&elem, jb, jsq); - break; - case jqiIs: - if (JsonbType(jb) == jbvScalar) - { - JsonbIterator *it; - int32 r; - JsonbValue v; - - it = JsonbIteratorInit(jb->val.binary.data); - - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_BEGIN_ARRAY); - Assert(v.val.array.rawScalar == 1); - Assert(v.val.array.nElems == 1); - - r = JsonbIteratorNext(&it, &v, true); - Assert(r == WJB_ELEM); - - res = (jsqGetIsType(jsq) == JsonbType(&v)); - } - else - { - res = (jsqGetIsType(jsq) == JsonbType(jb)); - } - break; - default: - elog(ERROR,"Wrong state: %d", jsq->type); - } - - return res; -} - -PG_FUNCTION_INFO_V1(jsquery_json_exec); -Datum -jsquery_json_exec(PG_FUNCTION_ARGS) -{ - JsQuery *jq = PG_GETARG_JSQUERY(0); - Jsonb *jb = PG_GETARG_JSONB_P(1); - bool res; - JsonbValue jbv; - JsQueryItem jsq; - - jbv.type = jbvBinary; - jbv.val.binary.data = &jb->root; - jbv.val.binary.len = VARSIZE_ANY_EXHDR(jb); - - jsqInit(&jsq, jq); - - res = recursiveExecute(&jsq, &jbv, NULL); - - PG_FREE_IF_COPY(jq, 0); - PG_FREE_IF_COPY(jb, 1); - - PG_RETURN_BOOL(res); -} - -PG_FUNCTION_INFO_V1(json_jsquery_exec); -Datum -json_jsquery_exec(PG_FUNCTION_ARGS) -{ - Jsonb *jb = PG_GETARG_JSONB_P(0); - JsQuery *jq = PG_GETARG_JSQUERY(1); - bool res; - JsonbValue jbv; - JsQueryItem jsq; - - jbv.type = jbvBinary; - jbv.val.binary.data = &jb->root; - jbv.val.binary.len = VARSIZE_ANY_EXHDR(jb); - - jsqInit(&jsq, jq); - - res = recursiveExecute(&jsq, &jbv, NULL); - - PG_FREE_IF_COPY(jb, 0); - PG_FREE_IF_COPY(jq, 1); - - PG_RETURN_BOOL(res); -} - -static int -compareJsQuery(JsQueryItem *v1, JsQueryItem *v2) -{ - JsQueryItem elem1, elem2; - int32 res = 0; - - check_stack_depth(); - - if (v1->type != v2->type) - return (v1->type > v2->type) ? 1 : -1; - - switch(v1->type) - { - case jqiNull: - case jqiCurrent: - case jqiLength: - case jqiAny: - case jqiAnyArray: - case jqiAnyKey: - case jqiAll: - case jqiAllArray: - case jqiAllKey: - break; - case jqiIndexArray: - if (v1->arrayIndex != v2->arrayIndex) - res = (v1->arrayIndex > v2->arrayIndex) ? 1 : -1; - break; - case jqiKey: - case jqiString: - { - int32 len1, len2; - char *s1, *s2; - - s1 = jsqGetString(v1, &len1); - s2 = jsqGetString(v2, &len2); - - if (len1 != len2) - res = (len1 > len2) ? 1 : -1; - else - res = memcmp(s1, s2, len1); - } - break; - case jqiNumeric: - res = compareNumeric(jsqGetNumeric(v1), jsqGetNumeric(v2)); - break; - case jqiBool: - if (jsqGetBool(v1) != jsqGetBool(v2)) - res = (jsqGetBool(v1) > jsqGetBool(v2)) ? 1 : -1; - break; - case jqiArray: - if (v1->array.nelems != v2->array.nelems) - res = (v1->array.nelems > v2->array.nelems) ? 1 : -1; - - while(res == 0 && jsqIterateArray(v1, &elem1) && jsqIterateArray(v2, &elem2)) - res = compareJsQuery(&elem1, &elem2); - break; - case jqiAnd: - case jqiOr: - jsqGetLeftArg(v1, &elem1); - jsqGetLeftArg(v2, &elem2); - - res = compareJsQuery(&elem1, &elem2); - - if (res == 0) - { - jsqGetRightArg(v1, &elem1); - jsqGetRightArg(v2, &elem2); - - res = compareJsQuery(&elem1, &elem2); - } - break; - case jqiEqual: - case jqiIn: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - case jqiNot: - jsqGetArg(v1, &elem1); - jsqGetArg(v2, &elem2); - - res = compareJsQuery(&elem1, &elem2); - break; - default: - elog(ERROR, "Unknown JsQueryItem type: %d", v1->type); - } - - if (res == 0) - { - if (jsqGetNext(v1, &elem1)) - { - if (jsqGetNext(v2, &elem2)) - res = compareJsQuery(&elem1, &elem2); - else - res = 1; - } - else if (jsqGetNext(v2, &elem2)) - { - res = -1; - } - } - - return res; -} - -PG_FUNCTION_INFO_V1(jsquery_cmp); -Datum -jsquery_cmp(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_INT32(res); -} - -PG_FUNCTION_INFO_V1(jsquery_lt); -Datum -jsquery_lt(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res < 0); -} - -PG_FUNCTION_INFO_V1(jsquery_le); -Datum -jsquery_le(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res <= 0); -} - -PG_FUNCTION_INFO_V1(jsquery_eq); -Datum -jsquery_eq(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res == 0); -} - -PG_FUNCTION_INFO_V1(jsquery_ne); -Datum -jsquery_ne(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res != 0); -} - -PG_FUNCTION_INFO_V1(jsquery_ge); -Datum -jsquery_ge(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res >= 0); -} - -PG_FUNCTION_INFO_V1(jsquery_gt); -Datum -jsquery_gt(PG_FUNCTION_ARGS) -{ - JsQuery *jq1 = PG_GETARG_JSQUERY(0); - JsQuery *jq2 = PG_GETARG_JSQUERY(1); - int32 res; - JsQueryItem v1, v2; - - jsqInit(&v1, jq1); - jsqInit(&v2, jq2); - - res = compareJsQuery(&v1, &v2); - - PG_FREE_IF_COPY(jq1, 0); - PG_FREE_IF_COPY(jq2, 1); - - PG_RETURN_BOOL(res > 0); -} - -static void -hashJsQuery(JsQueryItem *v, pg_crc32 *crc) -{ - JsQueryItem elem; - - check_stack_depth(); - - COMP_CRC32(*crc, &v->type, sizeof(v->type)); - - switch(v->type) - { - case jqiNull: - COMP_CRC32(*crc, "null", 5); - break; - case jqiKey: - case jqiString: - { - int32 len; - char *s; - - s = jsqGetString(v, &len); - - if (v->type == jqiKey) - len++; /* include trailing '\0' */ - COMP_CRC32(*crc, s, len); - } - break; - case jqiNumeric: - *crc ^= (pg_crc32)DatumGetInt32(DirectFunctionCall1( - hash_numeric, - PointerGetDatum(jsqGetNumeric(v)))); - break; - case jqiBool: - { - bool b = jsqGetBool(v); - - COMP_CRC32(*crc, &b, 1); - } - break; - case jqiArray: - COMP_CRC32(*crc, &v->array.nelems, sizeof(v->array.nelems)); - while(jsqIterateArray(v, &elem)) - hashJsQuery(&elem, crc); - break; - case jqiAnd: - case jqiOr: - jsqGetLeftArg(v, &elem); - hashJsQuery(&elem, crc); - jsqGetRightArg(v, &elem); - hashJsQuery(&elem, crc); - break; - case jqiNot: - case jqiEqual: - case jqiIn: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - jsqGetArg(v, &elem); - hashJsQuery(&elem, crc); - break; - case jqiCurrent: - case jqiLength: - case jqiAny: - case jqiAnyArray: - case jqiAnyKey: - case jqiAll: - case jqiAllArray: - case jqiAllKey: - break; - case jqiIndexArray: - COMP_CRC32(*crc, &v->arrayIndex, sizeof(v->arrayIndex)); - break; - default: - elog(ERROR, "Unknown JsQueryItem type: %d", v->type); - } -} - -PG_FUNCTION_INFO_V1(jsquery_hash); -Datum -jsquery_hash(PG_FUNCTION_ARGS) -{ - JsQuery *jq = PG_GETARG_JSQUERY(0); - JsQueryItem v; - pg_crc32 res; - - INIT_CRC32(res); - jsqInit(&v, jq); - hashJsQuery(&v, &res); - FIN_CRC32(res); - - PG_FREE_IF_COPY(jq, 0); - - PG_RETURN_INT32(res); -} - diff --git a/jsquery/jsquery_scan.l b/jsquery/jsquery_scan.l deleted file mode 100644 index e73bdd7f10..0000000000 --- a/jsquery/jsquery_scan.l +++ /dev/null @@ -1,508 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_scan.l - * Lexical parser for jsquery datatype - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_scan.l - * - *------------------------------------------------------------------------- - */ - -%{ -#include "mb/pg_wchar.h" - -static string scanstring; - -/* No reason to constrain amount of data slurped */ -/* #define YY_READ_BUF_SIZE 16777216 */ - -/* Handles to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; -static char *scanbuf; -static int scanbuflen; - -static void addstring(bool init, char *s, int l); -static void addchar(bool init, char s); -static int checkSpecialVal(void); /* examine scanstring for the special value */ -static JsQueryHint checkHint(void); - -static void parseUnicode(char *s, int l); - -%} - -%option 8bit -%option never-interactive -%option nodefault -%option noinput -%option nounput -%option noyywrap -%option warn -%option prefix="jsquery_yy" -%option bison-bridge - -%x xQUOTED -%x xNONQUOTED -%x xCOMMENT - -special [\%\$\.\[\]\(\)\|\&\!\=\<\>\@\#\,\*:] -any [^\%\$\.\[\]\(\)\|\&\!\=\<\>\@\#\,\* \t\n\r\f\\\"\/:] -blank [ \t\n\r\f] -unicode \\u[0-9A-Fa-f]{4} - -%% - -{special} { return *yytext; } - -{blank}+ { /* ignore */ } - -\/\* { - addchar(true, '\0'); - BEGIN xCOMMENT; - } - -[+-]?[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+ /* float */ { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; - return NUMERIC_P; - } - -[+-]?\.[0-9]+[eE][+-]?[0-9]+ /* float */ { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; - return NUMERIC_P; - } - -[+-]?([0-9]+)?\.[0-9]+ { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; - return NUMERIC_P; - } - -[+-][0-9]+ { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; - return NUMERIC_P; - } - -[0-9]+ { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; - return INT_P; - } - -{any}+ { - addstring(true, yytext, yyleng); - BEGIN xNONQUOTED; - } - -\" { - addchar(true, '\0'); - BEGIN xQUOTED; - } - -\\ { - yyless(0); - addchar(true, '\0'); - BEGIN xNONQUOTED; - } - -{any}+ { - addstring(false, yytext, yyleng); - } - -{blank}+ { - yylval->str = scanstring; - BEGIN INITIAL; - return checkSpecialVal(); - } - - -\/\* { - yylval->str = scanstring; - addchar(true, '\0'); - BEGIN xCOMMENT; - return checkSpecialVal(); - } - - -\/ { addchar(false, '/'); } - -({special}|\") { - yylval->str = scanstring; - yyless(0); - BEGIN INITIAL; - return checkSpecialVal(); - } - -<> { - yylval->str = scanstring; - BEGIN INITIAL; - return checkSpecialVal(); - } - -\\[\"\\] { addchar(false, yytext[1]); } - -\\b { addchar(false, '\b'); } - -\\f { addchar(false, '\f'); } - -\\n { addchar(false, '\n'); } - -\\r { addchar(false, '\r'); } - -\\t { addchar(false, '\t'); } - -{unicode}+ { parseUnicode(yytext, yyleng); } - -\\u { yyerror(NULL, "Unicode sequence is invalid"); } - -\\. { yyerror(NULL, "Escape sequence is invalid"); } - -\\ { yyerror(NULL, "Unexpected end after backslesh"); } - -<> { yyerror(NULL, "Unexpected end of quoted string"); } - -\" { - yylval->str = scanstring; - BEGIN INITIAL; - return STRING_P; - } - -[^\\\"]+ { addstring(false, yytext, yyleng); } - -<> { yyterminate(); } - -\*\/ { - BEGIN INITIAL; - - if ((yylval->hint = checkHint()) != jsqIndexDefault) - return HINT_P; - } - -[^\*]+ { addstring(false, yytext, yyleng); } - -\* { addchar(false, '*'); } - -<> { yyerror(NULL, "Unexpected end of comment"); } - -%% - -void -yyerror(JsQueryParseItem **result, const char *message) -{ - if (*yytext == YY_END_OF_BUFFER_CHAR) - { - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("bad jsquery representation"), - /* translator: %s is typically "syntax error" */ - errdetail("%s at end of input", message))); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("bad jsquery representation"), - /* translator: first %s is typically "syntax error" */ - errdetail("%s at or near \"%s\"", message, yytext))); - } -} - -typedef struct keyword -{ - int16 len; - bool lowercase; - int val; - char *keyword; -} keyword; - -/* - * Array of key words should be sorted by length and then - * alphabetical order - */ - -static keyword keywords[] = { - { 2, false, IN_P, "in"}, - { 2, false, IS_P, "is"}, - { 2, false, OR_P, "or"}, - { 3, false, AND_P, "and"}, - { 3, false, NOT_P, "not"}, - { 4, true, NULL_P, "null"}, - { 4, true, TRUE_P, "true"}, - { 5, false, ARRAY_T, "array"}, - { 5, true, FALSE_P, "false"}, - { 6, false, OBJECT_T, "object"}, - { 6, false, STRING_T, "string"}, - { 7, false, BOOLEAN_T, "boolean"}, - { 7, false, NUMERIC_T, "numeric"} -}; - -static int -checkSpecialVal() -{ - int res = STRING_P; - int diff; - keyword *StopLow = keywords, - *StopHigh = keywords + lengthof(keywords), - *StopMiddle; - - if (scanstring.len > keywords[lengthof(keywords) - 1].len) - return res; - - while(StopLow < StopHigh) - { - StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); - - if (StopMiddle->len == scanstring.len) - diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val, scanstring.len); - else - diff = StopMiddle->len - scanstring.len; - - if (diff < 0) - StopLow = StopMiddle + 1; - else if (diff > 0) - StopHigh = StopMiddle; - else - { - if (StopMiddle->lowercase) - diff = strncmp(StopMiddle->keyword, scanstring.val, scanstring.len); - - if (diff == 0) - res = StopMiddle->val; - - break; - } - } - - return res; -} - -static JsQueryHint -checkHint() -{ - if (scanstring.len <= 2 || strncmp(scanstring.val, "--", 2) != 0) - return jsqIndexDefault; - - scanstring.val += 2; - scanstring.len -= 2; - - while(scanstring.len > 0 && isspace(*scanstring.val)) - { - scanstring.val++; - scanstring.len--; - } - - if (scanstring.len >= 5 && pg_strncasecmp(scanstring.val, "index", 5) == 0) - return jsqForceIndex; - - if (scanstring.len >= 7 && pg_strncasecmp(scanstring.val, "noindex", 7) == 0) - return jsqNoIndex; - - return jsqIndexDefault; -} -/* - * Called before any actual parsing is done - */ -static void -jsquery_scanner_init(const char *str, int slen) -{ - if (slen <= 0) - slen = strlen(str); - - /* - * Might be left over after ereport() - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); - - /* - * Make a scan buffer with special termination needed by flex. - */ - - scanbuflen = slen; - scanbuf = palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); - - BEGIN(INITIAL); -} - - -/* - * Called after parsing is done to clean up after jsquery_scanner_init() - */ -static void -jsquery_scanner_finish(void) -{ - yy_delete_buffer(scanbufhandle); - pfree(scanbuf); -} - -static void -addstring(bool init, char *s, int l) { - if (init) { - scanstring.total = 32; - scanstring.val = palloc(scanstring.total); - scanstring.len = 0; - } - - if (s && l) { - while(scanstring.len + l + 1 >= scanstring.total) { - scanstring.total *= 2; - scanstring.val = repalloc(scanstring.val, scanstring.total); - } - - memcpy(scanstring.val + scanstring.len, s, l); - scanstring.len += l; - } -} - -static void -addchar(bool init, char s) { - if (init) - { - scanstring.total = 32; - scanstring.val = palloc(scanstring.total); - scanstring.len = 0; - } - else if(scanstring.len + 1 >= scanstring.total) - { - scanstring.total *= 2; - scanstring.val = repalloc(scanstring.val, scanstring.total); - } - - scanstring.val[ scanstring.len ] = s; - if (s != '\0') - scanstring.len++; -} - -JsQueryParseItem* -parsejsquery(const char *str, int len) { - JsQueryParseItem *parseresult; - - jsquery_scanner_init(str, len); - - if (jsquery_yyparse((void*)&parseresult) != 0) - jsquery_yyerror(NULL, "bugus input"); - - jsquery_scanner_finish(); - - return parseresult; -} - -static int -hexval(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 0xA; - if (c >= 'A' && c <= 'F') - return c - 'A' + 0xA; - elog(ERROR, "invalid hexadecimal digit"); - return 0; /* not reached */ -} - -/* - * parseUnicode was adopted from json_lex_string() in - * src/backend/utils/adt/json.c - */ -static void -parseUnicode(char *s, int l) -{ - int i, j; - int ch = 0; - int hi_surrogate = -1; - - Assert(l % 6 /* \uXXXX */ == 0); - - for(i = 0; i < l / 6; i++) - { - ch = 0; - - for(j=0; j<4; j++) - ch = (ch << 4) | hexval(s[ i*6 + 2 + j]); - - if (ch >= 0xd800 && ch <= 0xdbff) - { - if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type jsquery"), - errdetail("Unicode high surrogate must not follow a high surrogate."))); - hi_surrogate = (ch & 0x3ff) << 10; - continue; - } - else if (ch >= 0xdc00 && ch <= 0xdfff) - { - if (hi_surrogate == -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type jsquery"), - errdetail("Unicode low surrogate must follow a high surrogate."))); - ch = 0x10000 + hi_surrogate + (ch & 0x3ff); - hi_surrogate = -1; - } - - if (hi_surrogate != -1) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type jsquery"), - errdetail("Unicode low surrogate must follow a high surrogate."))); - - /* - * For UTF8, replace the escape sequence by the actual - * utf8 character in lex->strval. Do this also for other - * encodings if the escape designates an ASCII character, - * otherwise raise an error. - */ - - if (ch == 0) - { - /* We can't allow this, since our TEXT type doesn't */ - ereport(ERROR, - (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), - errmsg("unsupported Unicode escape sequence"), - errdetail("\\u0000 cannot be converted to text."))); - } - else if (GetDatabaseEncoding() == PG_UTF8) - { - char utf8str[5]; - int utf8len; - - unicode_to_utf8(ch, (unsigned char *) utf8str); - utf8len = pg_utf_mblen((unsigned char *) utf8str); - addstring(false, utf8str, utf8len); - } - else if (ch <= 0x007f) - { - /* - * This is the only way to designate things like a - * form feed character in JSON, so it's useful in all - * encodings. - */ - addchar(false, (char) ch); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type jsquery"), - errdetail("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8."))); - } - - hi_surrogate = -1; - } -} - - diff --git a/jsquery/jsquery_support.c b/jsquery/jsquery_support.c deleted file mode 100644 index ee63c8c76c..0000000000 --- a/jsquery/jsquery_support.c +++ /dev/null @@ -1,251 +0,0 @@ -/*------------------------------------------------------------------------- - * - * jsquery_support.c - * Functions and operations to support jsquery - * - * Copyright (c) 2014, PostgreSQL Global Development Group - * Author: Teodor Sigaev - * - * IDENTIFICATION - * contrib/jsquery/jsquery_support.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "jsquery.h" - -#define read_byte(v, b, p) do { \ - (v) = *(uint8*)((b) + (p)); \ - (p) += 1; \ -} while(0) \ - -#define read_int32(v, b, p) do { \ - (v) = *(uint32*)((b) + (p)); \ - (p) += sizeof(int32); \ -} while(0) \ - -void -alignStringInfoInt(StringInfo buf) -{ - switch(INTALIGN(buf->len) - buf->len) - { - case 3: - appendStringInfoCharMacro(buf, 0); - case 2: - appendStringInfoCharMacro(buf, 0); - case 1: - appendStringInfoCharMacro(buf, 0); - default: - break; - } -} - -void -jsqInit(JsQueryItem *v, JsQuery *js) -{ - jsqInitByBuffer(v, VARDATA(js), 0); -} - -void -jsqInitByBuffer(JsQueryItem *v, char *base, int32 pos) -{ - v->base = base; - - read_byte(v->type, base, pos); - - v->hint = v->type & JSQ_HINT_MASK; - v->type &= ~JSQ_HINT_MASK; - - switch(INTALIGN(pos) - pos) - { - case 3: pos++; - case 2: pos++; - case 1: pos++; - default: break; - } - - read_int32(v->nextPos, base, pos); - - switch(v->type) - { - case jqiNull: - case jqiCurrent: - case jqiLength: - case jqiAny: - case jqiAnyArray: - case jqiAnyKey: - case jqiAll: - case jqiAllArray: - case jqiAllKey: - break; - case jqiIndexArray: - read_int32(v->arrayIndex, base, pos); - break; - case jqiKey: - case jqiString: - read_int32(v->value.datalen, base, pos); - /* follow next */ - case jqiNumeric: - case jqiBool: - case jqiIs: - v->value.data = base + pos; - break; - case jqiArray: - read_int32(v->array.nelems, base, pos); - v->array.current = 0; - v->array.arrayPtr = (int32*)(base + pos); - break; - case jqiAnd: - case jqiOr: - read_int32(v->args.left, base, pos); - read_int32(v->args.right, base, pos); - break; - case jqiEqual: - case jqiLess: - case jqiGreater: - case jqiLessOrEqual: - case jqiGreaterOrEqual: - case jqiContains: - case jqiContained: - case jqiOverlap: - case jqiIn: - case jqiNot: - read_int32(v->arg, base, pos); - break; - default: - abort(); - elog(ERROR, "Unknown type: %d", v->type); - } -} - -void -jsqGetArg(JsQueryItem *v, JsQueryItem *a) -{ - Assert( - v->type == jqiEqual || - v->type == jqiLess || - v->type == jqiGreater || - v->type == jqiLessOrEqual || - v->type == jqiGreaterOrEqual || - v->type == jqiContains || - v->type == jqiContained || - v->type == jqiOverlap || - v->type == jqiIn || - v->type == jqiNot - ); - - jsqInitByBuffer(a, v->base, v->arg); -} - -bool -jsqGetNext(JsQueryItem *v, JsQueryItem *a) -{ - if (v->nextPos > 0) - { - Assert( - v->type == jqiKey || - v->type == jqiAny || - v->type == jqiIndexArray || - v->type == jqiAnyArray || - v->type == jqiAnyKey || - v->type == jqiAll || - v->type == jqiAllArray || - v->type == jqiAllKey || - v->type == jqiCurrent || - v->type == jqiLength - ); - - if (a) - jsqInitByBuffer(a, v->base, v->nextPos); - return true; - } - - return false; -} - -void -jsqGetLeftArg(JsQueryItem *v, JsQueryItem *a) -{ - Assert( - v->type == jqiAnd || - v->type == jqiOr - ); - - jsqInitByBuffer(a, v->base, v->args.left); -} - -void -jsqGetRightArg(JsQueryItem *v, JsQueryItem *a) -{ - Assert( - v->type == jqiAnd || - v->type == jqiOr - ); - - jsqInitByBuffer(a, v->base, v->args.right); -} - -bool -jsqGetBool(JsQueryItem *v) -{ - Assert(v->type == jqiBool); - - return (bool)*v->value.data; -} - -Numeric -jsqGetNumeric(JsQueryItem *v) -{ - Assert(v->type == jqiNumeric); - - return (Numeric)v->value.data; -} - -int32 -jsqGetIsType(JsQueryItem *v) -{ - Assert(v->type = jqiIs); - - return (int32)*v->value.data; -} - -char* -jsqGetString(JsQueryItem *v, int32 *len) -{ - Assert( - v->type == jqiKey || - v->type == jqiString - ); - - if (len) - *len = v->value.datalen; - return v->value.data; -} - -void -jsqIterateInit(JsQueryItem *v) -{ - Assert(v->type == jqiArray); - - v->array.current = 0; -} - -bool -jsqIterateArray(JsQueryItem *v, JsQueryItem *e) -{ - Assert(v->type == jqiArray); - - if (v->array.current < v->array.nelems) - { - jsqInitByBuffer(e, v->base, v->array.arrayPtr[v->array.current]); - v->array.current++; - return true; - } - else - { - return false; - } -} - diff --git a/jsquery/sql/jsquery.sql b/jsquery/sql/jsquery.sql deleted file mode 100644 index d264955adb..0000000000 --- a/jsquery/sql/jsquery.sql +++ /dev/null @@ -1,548 +0,0 @@ -CREATE EXTENSION jsquery; - -set escape_string_warning=off; -set standard_conforming_strings=on; - -CREATE TABLE test_jsquery (v jsonb); - -\copy test_jsquery from 'data/test_jsquery.data' - -select 'asd.zzz = 13'::jsquery; -select 'asd.zzz < 13'::jsquery; -select 'asd(zzz < 13)'::jsquery; -select 'asd(zzz < 13 AND x = true)'::jsquery; -select 'asd(zzz < 13 AND x = "true")'::jsquery; -select 'asd(zzz < 13 AND x.zxc = "true")'::jsquery; -select 'asd(zzz < 13 OR #.zxc = "true" /* test */)'::jsquery; -select 'asd(* < 13 AND /* ttt */ #.zxc = "true")'::jsquery; -select '(* < 13 AND #.zxc = "true")'::jsquery; -select '* < 13 AND #.zxc/* t2 */ = "true"'::jsquery; -select '* < 13 AND #.zxc"x" = "true"'::jsquery; - -select 'a < 1'::jsquery; -select 'a < -1'::jsquery; -select 'a < +1'::jsquery; -select 'a < .1'::jsquery; -select 'a < -.1'::jsquery; -select 'a < +.1'::jsquery; -select 'a < 0.1'::jsquery; -select 'a < -0.1'::jsquery; -select 'a < +0.1'::jsquery; -select 'a < 10.1'::jsquery; -select 'a < -10.1'::jsquery; -select 'a < +10.1'::jsquery; -select 'a < 1e1'::jsquery; -select 'a < -1e1'::jsquery; -select 'a < +1e1'::jsquery; -select 'a < .1e1'::jsquery; -select 'a < -.1e1'::jsquery; -select 'a < +.1e1'::jsquery; -select 'a < 0.1e1'::jsquery; -select 'a < -0.1e1'::jsquery; -select 'a < +0.1e1'::jsquery; -select 'a < 10.1e1'::jsquery; -select 'a < -10.1e1'::jsquery; -select 'a < +10.1e1'::jsquery; -select 'a < 1e-1'::jsquery; -select 'a < -1e-1'::jsquery; -select 'a < +1e-1'::jsquery; -select 'a < .1e-1'::jsquery; -select 'a < -.1e-1'::jsquery; -select 'a < +.1e-1'::jsquery; -select 'a < 0.1e-1'::jsquery; -select 'a < -0.1e-1'::jsquery; -select 'a < +0.1e-1'::jsquery; -select 'a < 10.1e-1'::jsquery; -select 'a < -10.1e-1'::jsquery; -select 'a < +10.1e-1'::jsquery; -select 'a < 1e+1'::jsquery; -select 'a < -1e+1'::jsquery; -select 'a < +1e+1'::jsquery; -select 'a < .1e+1'::jsquery; -select 'a < -.1e+1'::jsquery; -select 'a < +.1e+1'::jsquery; -select 'a < 0.1e+1'::jsquery; -select 'a < -0.1e+1'::jsquery; -select 'a < +0.1e+1'::jsquery; -select 'a < 10.1e+1'::jsquery; -select 'a < -10.1e+1'::jsquery; -select 'a < +10.1e+1'::jsquery; - -select 'a in (0,1,2)'::jsquery; -select 'a IN (0,null, "null", xxx, "zzz", 2)'::jsquery; - -select 'not < 1'::jsquery; -select 'not not < 1'::jsquery; -select 'not( not < 1)'::jsquery; -select 'not.x < 1'::jsquery; -select 'x.not < 1'::jsquery; -select 'a.%(not x > 0 and not (y < 0 or z = 0))'::jsquery; - -select 'is < 1'::jsquery; -select 'in < 1'::jsquery; - -select 'not is < 1'::jsquery; -select 'not in < 1'::jsquery; - -select 'in in (1,2)'::jsquery; -select 'is in (1,2)'::jsquery; -select 'not in (1,2)'::jsquery; - -select 'in is numeric'::jsquery; -select 'is is numeric'::jsquery; -select 'not is numeric'::jsquery; - -select 'not.in < 1'::jsquery; -select 'not.is < 1'::jsquery; -select 'not.not < 1'::jsquery; -select 'in.in < 1'::jsquery; -select 'in.is < 1'::jsquery; -select 'in.not < 1'::jsquery; -select 'is.in < 1'::jsquery; -select 'is.is < 1'::jsquery; -select 'is.not < 1'::jsquery; - -select 'a.b.#4 > 4'::jsquery; -select 'a.b.#10203.* > 4'::jsquery; - -select '{"a": {"b": null}}'::jsonb @@ 'a.b = 1'; -select '{"a": {"b": null}}'::jsonb @@ 'a.b = null'; -select '{"a": {"b": null}}'::jsonb @@ 'a.b = false'; -select '{"a": {"b": false}}'::jsonb @@ 'a.b = false'; -select '{"a": {"b": false}}'::jsonb @@ 'a.b = true'; -select '{"a": {"b": true}}'::jsonb @@ 'a.b = true'; - - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 1'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 1'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 1'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 1'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 1'; - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 2'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 2'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 2'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 2'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 2'; - -select '{"a": {"b": 1}}'::jsonb @@ 'a.b = 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b < 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b <= 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b >= 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.b > 0'; - -select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; -select '{"a": {"b": 1}}'::jsonb @@ '*.b > 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; -select '{"a": {"b": 1}}'::jsonb @@ 'a.* > 0'; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 1 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b @> [ 1,2,3,4 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b <@ [ 1,2,3,4 ]'; - -select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 4'; -select '[{"a": 2}, {"a": 3}]'::jsonb @@ '*.a = 3'; - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a = 4'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a = 4'; - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 1 OR a=3)'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 OR a=1)'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=1)'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#(a = 3 and a=2)' as "false"; -select '[{"a": 2, "b":3}, {"a": 3, "b": 1}]'::jsonb @@ '#(b = 1 and a=3)'; - -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.a.a = 4'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.a.a = 4'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '*.#.a.a = 4'; -select '[{"a": 2}, {"a": 3}, {"a": {"a":4}}]'::jsonb @@ '#.*.a.a = 4'; - -select '{"a": 1}'::jsonb @@ 'a in (0,1,2)'; -select '{"a": 1}'::jsonb @@ 'a in (0,2)'; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#=2'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 5 ]'; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a=*'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b=*'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.c=*'; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b = [1,2,3]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# = [1,2,3]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b && [1,2,3]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.# && [1,2,3]'; - -select 'asd.# = 3'::jsquery & 'zzz = true' | 'xxx.# = zero'; -select !'asd.# = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; -select !'asd.#3.f = 3'::jsquery & 'zzz = true' | !'xxx.# = zero'; - -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0]'::jsquery; -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,1]'::jsquery; -select '{"x":[0,1,1,2]}'::jsonb @@ 'x @> [1,0,3]'::jsquery; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b && [ 2 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ '*.b($ && [ 2 ])'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b && [ 2 ]'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.$.b ($ && [ 2 ])'; - -select '[1,2,3]'::jsonb @@ '# && [2]'; -select '[1,2,3]'::jsonb @@ '#($ && [2])'; -select '[1,2,3]'::jsonb @@ '$ && [2]'; -select '[1,2,3]'::jsonb @@ '$ ($ && [2])'; -select '[1,2,3]'::jsonb @@ '$ = 2'; -select '[1,2,3]'::jsonb @@ '# = 2'; -select '[1,2,3]'::jsonb @@ '#.$ = 2'; -select '[1,2,3]'::jsonb @@ '#($ = 2)'; - -select '[3,4]'::jsonb @@ '#($ > 2 and $ < 5)'; -select '[3,4]'::jsonb @@ '# > 2 and # < 5'; -select '[1,6]'::jsonb @@ '#($ > 2 and $ < 5)'; -select '[1,6]'::jsonb @@ '# > 2 and # < 5'; - -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.b=3'; -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ 'a.%=3'; -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%.%="hey"'; -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%="hey"'; -select '{"a": {"b": 3, "c": "hey"}, "x": [5,6]}'::jsonb @@ '%=[5,6]'; - -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#1 = 2'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#2 = 2'; -select '{"a": {"b": [1,2,3]}}'::jsonb @@ 'a.b.#3 = 2'; -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#1.x = 2'; -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#2.x = 2'; -select '{"a": {"b": [{"x":1},{"x":2},{"x":3}]}}'::jsonb @@ 'a.b.#3.x = 2'; - -select '"XXX"'::jsonb @@ '$="XXX"'; -select '"XXX"'::jsonb @@ '#.$="XXX"'; - ---Unicode - -select 'a\t = "dollar \u0024 character"'::jsquery; -select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar \u0024 character"'; -select '{ "a": "dollar \u0024 character" }'::jsonb @@ '* = "dollar $ character"'; -select '{ "a": "dollar $ character" }'::jsonb @@ '* = "dollar \u0024 character"'; -select 'a\r = "\n\""'::jsquery; -select 'a\r = "\u0000"'::jsquery; -select 'a\r = \u0000'::jsquery; -select 'a\r = "\abcd"'::jsquery AS err; -select 'a\r = "\\abcd"'::jsquery; -select 'a\r = "x\u0000"'::jsquery; -select 'a\r = x\u0000'::jsquery; -select 'a\r = "x\abcd"'::jsquery AS err; -select 'a\r = "x\\abcd"'::jsquery; -select 'a\r = "x\u0000x"'::jsquery; -select 'a\r = x\u0000x'::jsquery; -select 'a\r = "x\abcdx"'::jsquery AS err; -select 'a\r = "x\\abcdx"'::jsquery; -select 'a\r = "\u0000x"'::jsquery; -select 'a\r = \u0000x'::jsquery; -select 'a\r = "\abcdx"'::jsquery AS err; -select 'a\r = "\\abcdx"'::jsquery; -select 'a\r = x"\\abcd"'::jsquery AS err; - ---IS - -select 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric OR as is string'::jsquery; -select '{"as": "xxx"}' @@ 'as IS string'::jsquery; -select '{"as": "xxx"}' @@ 'as IS boolean OR as is ARRAY OR as is ObJect OR as is Numeric'::jsquery; -select '{"as": 5}' @@ 'as is Numeric'::jsquery; -select '{"as": true}' @@ 'as is boolean'::jsquery; -select '{"as": false}' @@ 'as is boolean'::jsquery; -select '{"as": "false"}' @@ 'as is boolean'::jsquery; -select '["xxx"]' @@ '$ IS array'::jsquery; -select '{"as": false}' @@ '$ IS object'::jsquery; -select '"xxx"' @@ '$ IS string'::jsquery; -select '"xxx"' @@ '$ IS numeric'::jsquery; - ---hint - -select 'a /*-- noindex */ = 5'::jsquery; -select 'a /*-- index */ = 5'::jsquery; -select 'asd.# = 3'::jsquery & 'zzz /*-- noindex */ = true' | 'xxx.# /*-- index */ = zero'; -select 'a /*-- xxx */ = 5'::jsquery; -select 'a /* index */ = 5'::jsquery; -select 'a /* noindex */ = 5'::jsquery; -select 'a = /*-- noindex */ 5'::jsquery; -select 'a = /* noindex */ 5'::jsquery; - ---LENGTH -select 'a.@# = 4'::jsquery; -select 'a.@#.$ = 4'::jsquery as noerror; -select 'a.@#.a = 4'::jsquery as error; -select 'a.@#.* = 4'::jsquery as error; -select 'a.@#.% = 4'::jsquery as error; -select 'a.@#.# = 4'::jsquery as error; -select 'a.@#.*: = 4'::jsquery as error; -select 'a.@#.%: = 4'::jsquery as error; -select 'a.@#.#: = 4'::jsquery as error; -select 'a.@# (a = 5 or b = 6)'::jsquery as error; -select '[]' @@ '@# = 0'::jsquery; -select '[]' @@ '@# < 2'::jsquery; -select '[]' @@ '@# > 1'::jsquery; -select '[1]' @@ '@# = 0'::jsquery; -select '[1]' @@ '@# < 2'::jsquery; -select '[1]' @@ '@# > 1'::jsquery; -select '[1,2]' @@ '@# = 0'::jsquery; -select '[1,2]' @@ '@# < 2'::jsquery; -select '[1,2]' @@ '@# > 1'::jsquery; -select '[1,2]' @@ '@# in (1, 2)'::jsquery; -select '[1,2]' @@ '@# in (1, 3)'::jsquery; -select '{"a":[1,2]}' @@ '@# in (2, 4)'::jsquery; -select '{"a":[1,2]}' @@ 'a.@# in (2, 4)'::jsquery; -select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery; -select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery; -select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery; -select '{"a":[1,2]}' @@ '@# = 1'::jsquery; - ---ALL -select 'a.*: = 4'::jsquery; -select '%: = 4'::jsquery; -select '#:.i = 4'::jsquery; -select '[]' @@ '#: ($ > 1 and $ < 5)'::jsquery; -select '[2,3,4]' @@ '#: ($ > 1 and $ < 5)'::jsquery; -select '[2,3,5]' @@ '#: ($ > 1 and $ < 5)'::jsquery; -select '[2,3,5]' @@ '# ($ > 1 and $ < 5)'::jsquery; -select '[2,3,"x"]' @@ '#: ($ > 1 and $ < 5)'::jsquery; -select '{}' @@ '%: ($ > 1 and $ < 5)'::jsquery; -select '{}' @@ '*: ($ is object)'::jsquery; -select '"a"' @@ '*: is string'::jsquery; -select '1' @@ '*: is string'::jsquery; -select '{"a":2,"b":3,"c":4}' @@ '%: ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":5}' @@ '%: ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":5}' @@ '% ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":"x"}' @@ '%: ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":4}' @@ '*: ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":5}' @@ '*: ($ > 1 and $ < 5)'::jsquery; -select '{"a":2,"b":3,"c":4}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; -select '{"a":2,"b":3,"c":5}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; -select '{"b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 1 and $ < 5))'::jsquery; -select '{"b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 1 and $ < 5))'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":4}}' @@ '*: ($ is object OR ($ > 0 and $ < 5))'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR ($> 0 and $ < 5))'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '* ($ > 0 and $ < 5)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":{"ba":3, "bb":5}}' @@ '*: ($ is object OR $ is numeric)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is numeric)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":[5,6]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":8}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":"x"}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; -select '{"a":{"aa":1, "ab":2}, "b":[5,6, {"c":null}]}' @@ '*: ($ is object OR $ is array OR $ is numeric)'::jsquery; -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '%:.aa is numeric'::jsquery; -select '{"a":{"aa":1}, "b":{"aa":true, "bb":2}}' @@ '%:.aa is numeric'::jsquery; -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}, "aa":16}' @@ '*: (not $ is object or $.aa is numeric)'::jsquery; -select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '*: (not $ is object or $.aa is numeric or % is object)'::jsquery; -SELECT 'test.# IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64)'::jsquery; - -select '[]' @@ '(@# > 0 and #: = 16)'::jsquery; -select '[16]' @@ '(@# > 0 and #: = 16)'::jsquery; - ---extract entries for index scan - -SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); -SELECT gin_debug_query_path_value('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); -SELECT gin_debug_query_path_value('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); -SELECT gin_debug_query_path_value('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); -SELECT gin_debug_query_path_value('#(x = "a" and y > 0 and y < 1 and z > 0)'); -SELECT gin_debug_query_path_value('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); -SELECT gin_debug_query_path_value('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); -SELECT gin_debug_query_path_value('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); -SELECT gin_debug_query_path_value('%.x = 1'); -SELECT gin_debug_query_path_value('*.x = "b"'); -SELECT gin_debug_query_path_value('x && [1,2,3]'); -SELECT gin_debug_query_path_value('x @> [1,2,3]'); -SELECT gin_debug_query_path_value('x <@ [1,2,3]'); -SELECT gin_debug_query_path_value('x = *'); -SELECT gin_debug_query_path_value('x is boolean'); -SELECT gin_debug_query_path_value('x is string'); -SELECT gin_debug_query_path_value('x is numeric'); -SELECT gin_debug_query_path_value('x is array'); -SELECT gin_debug_query_path_value('x is object'); -SELECT gin_debug_query_path_value('#:(x=1) AND %:(y=1) AND *:(z=1)'); -SELECT gin_debug_query_path_value('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); -SELECT gin_debug_query_path_value('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); - -SELECT gin_debug_query_value_path('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5'); -SELECT gin_debug_query_value_path('NOT #(x=1) and NOT *(y=1) and NOT %(z=1) '); -SELECT gin_debug_query_value_path('#(NOT x=1) and *(NOT y=1) and %(NOT z=1) '); -SELECT gin_debug_query_value_path('NOT #(NOT x=1) and NOT *(NOT y=1) and NOT %(NOT z=1) '); -SELECT gin_debug_query_value_path('#(x = "a" and y > 0 and y < 1 and z > 0)'); -SELECT gin_debug_query_value_path('#(x = "a" and y /*-- index */ >= 0 and y < 1 and z > 0)'); -SELECT gin_debug_query_value_path('#(x /*-- noindex */ = "a" and y > 0 and y <= 1 and z /*-- index */ > 0)'); -SELECT gin_debug_query_value_path('x = 1 and (y /*-- index */ > 0 and y < 1 OR z > 0)'); -SELECT gin_debug_query_value_path('%.x = 1'); -SELECT gin_debug_query_value_path('*.x = "b"'); -SELECT gin_debug_query_value_path('x && [1,2,3]'); -SELECT gin_debug_query_value_path('x @> [1,2,3]'); -SELECT gin_debug_query_value_path('x <@ [1,2,3]'); -SELECT gin_debug_query_value_path('x = [1,2,3]'); -SELECT gin_debug_query_value_path('x = *'); -SELECT gin_debug_query_value_path('x is boolean'); -SELECT gin_debug_query_value_path('x is string'); -SELECT gin_debug_query_value_path('x is numeric'); -SELECT gin_debug_query_value_path('x is array'); -SELECT gin_debug_query_value_path('x is object'); -SELECT gin_debug_query_value_path('#:(x=1) AND %:(y=1) AND *:(z=1)'); -SELECT gin_debug_query_value_path('#:(NOT x=1) AND %:(NOT y=1) AND *:(NOT z=1)'); -SELECT gin_debug_query_value_path('NOT #:(NOT x=1) AND NOT %:(NOT y=1) AND NOT *:(NOT z=1)'); -SELECT gin_debug_query_value_path('(@# > 0 and #: = 16)'); -SELECT gin_debug_query_value_path('*.@# ($ = 4 or $ = 2)'); - ----table and index - -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 0; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 19; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 < 19; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 >= 19; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 <= 19; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 = 19; -select count(*) from test_jsquery where (v->>'review_helpful_votes')::int4 > 16 AND - (v->>'review_helpful_votes')::int4 < 20; - - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; -select count(*) from test_jsquery where v @@ 'customer_id = null'; -select count(*) from test_jsquery where v @@ 'review_votes = true'; -select count(*) from test_jsquery where v @@ 'product_group = false'; -select count(*) from test_jsquery where v @@ 't = *'; -select count(*) from test_jsquery where v @@ 't is boolean'; -select count(*) from test_jsquery where v @@ 't is string'; -select count(*) from test_jsquery where v @@ 't is numeric'; -select count(*) from test_jsquery where v @@ 't is array'; -select count(*) from test_jsquery where v @@ 't is object'; -select count(*) from test_jsquery where v @@ '$ is boolean'; -select count(*) from test_jsquery where v @@ '$ is string'; -select count(*) from test_jsquery where v @@ '$ is numeric'; -select count(*) from test_jsquery where v @@ '$ is array'; -select count(*) from test_jsquery where v @@ '$ is object'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; -select count(*) from test_jsquery where v @@ '$ > 2'; -select count(*) from test_jsquery where v @@ '$ = false'; - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; -select v from test_jsquery where v @@ 'array && [2,3]' order by v; -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - -create index t_idx on test_jsquery using gin (v jsonb_value_path_ops); -set enable_seqscan = off; - -explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; -select count(*) from test_jsquery where v @@ 'customer_id = null'; -select count(*) from test_jsquery where v @@ 'review_votes = true'; -select count(*) from test_jsquery where v @@ 'product_group = false'; -select count(*) from test_jsquery where v @@ 't = *'; -select count(*) from test_jsquery where v @@ 't is boolean'; -select count(*) from test_jsquery where v @@ 't is string'; -select count(*) from test_jsquery where v @@ 't is numeric'; -select count(*) from test_jsquery where v @@ 't is array'; -select count(*) from test_jsquery where v @@ 't is object'; -select count(*) from test_jsquery where v @@ '$ is boolean'; -select count(*) from test_jsquery where v @@ '$ is string'; -select count(*) from test_jsquery where v @@ '$ is numeric'; -select count(*) from test_jsquery where v @@ '$ is array'; -select count(*) from test_jsquery where v @@ '$ is object'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; -select count(*) from test_jsquery where v @@ '$ > 2'; -select count(*) from test_jsquery where v @@ '$ = false'; - -explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; -select v from test_jsquery where v @@ 'array && [2,3]' order by v; -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - -drop index t_idx; - -create index t_idx on test_jsquery using gin (v jsonb_path_value_ops); -set enable_seqscan = off; - -explain (costs off) select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; - -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 0'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes < 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes >= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes <= 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes = 19'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16' AND - v @@ 'review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes > 16 and review_helpful_votes < 20'; -select count(*) from test_jsquery where v @@ 'review_helpful_votes ($ > 16 and $ < 20)'; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids(# = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#($ = "0440180295") '; -select count(*) from test_jsquery where v @@ 'similar_product_ids && ["0440180295"] and product_sales_rank > 300000'; -select count(*) from test_jsquery where v @@ 'similar_product_ids <@ ["B00000DG0U", "B00004SQXU", "B0001XAM18", "B00000FDBU", "B00000FDBV", "B000002H2H", "B000002H6C", "B000002H5E", "B000002H97", "B000002HMH"]'; -select count(*) from test_jsquery where v @@ 'similar_product_ids @> ["B000002H2H", "B000002H6C"]'; -select count(*) from test_jsquery where v @@ 'customer_id = null'; -select count(*) from test_jsquery where v @@ 'review_votes = true'; -select count(*) from test_jsquery where v @@ 'product_group = false'; -select count(*) from test_jsquery where v @@ 't = *'; -select count(*) from test_jsquery where v @@ 't is boolean'; -select count(*) from test_jsquery where v @@ 't is string'; -select count(*) from test_jsquery where v @@ 't is numeric'; -select count(*) from test_jsquery where v @@ 't is array'; -select count(*) from test_jsquery where v @@ 't is object'; -select count(*) from test_jsquery where v @@ '$ is boolean'; -select count(*) from test_jsquery where v @@ '$ is string'; -select count(*) from test_jsquery where v @@ '$ is numeric'; -select count(*) from test_jsquery where v @@ '$ is array'; -select count(*) from test_jsquery where v @@ '$ is object'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is numeric'; -select count(*) from test_jsquery where v @@ 'similar_product_ids.#: is string'; -select count(*) from test_jsquery where v @@ 'NOT similar_product_ids.#: (NOT $ = "0440180295")'; -select count(*) from test_jsquery where v @@ '$ > 2'; -select count(*) from test_jsquery where v @@ '$ = false'; - -explain (costs off) select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array && [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array @> [2,3]' order by v; -explain (costs off) select v from test_jsquery where v @@ 'array = [2,3]' order by v; - -select v from test_jsquery where v @@ 'array <@ [2,3]' order by v; -select v from test_jsquery where v @@ 'array && [2,3]' order by v; -select v from test_jsquery where v @@ 'array @> [2,3]' order by v; -select v from test_jsquery where v @@ 'array = [2,3]' order by v; - -RESET enable_seqscan; diff --git a/jsquery/travis/dep-ubuntu-llvm.sh b/jsquery/travis/dep-ubuntu-llvm.sh deleted file mode 100644 index e640d5b5b2..0000000000 --- a/jsquery/travis/dep-ubuntu-llvm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cat ./travis/llvm-snapshot.gpg.key | sudo apt-key add - -echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-$(lsb_release -cs)-$LLVM_VER main" | sudo tee /etc/apt/sources.list.d/llvm.list diff --git a/jsquery/travis/dep-ubuntu-postgres.sh b/jsquery/travis/dep-ubuntu-postgres.sh deleted file mode 100644 index 41c7d34643..0000000000 --- a/jsquery/travis/dep-ubuntu-postgres.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cat ./travis/postgresql.gpg.key | sudo apt-key add - -echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PG_VER" | sudo tee /etc/apt/sources.list.d/pgdg.list diff --git a/jsquery/travis/llvm-snapshot.gpg.key b/jsquery/travis/llvm-snapshot.gpg.key deleted file mode 100644 index aa6b105aa3..0000000000 --- a/jsquery/travis/llvm-snapshot.gpg.key +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.12 (GNU/Linux) - -mQINBFE9lCwBEADi0WUAApM/mgHJRU8lVkkw0CHsZNpqaQDNaHefD6Rw3S4LxNmM -EZaOTkhP200XZM8lVdbfUW9xSjA3oPldc1HG26NjbqqCmWpdo2fb+r7VmU2dq3NM -R18ZlKixiLDE6OUfaXWKamZsXb6ITTYmgTO6orQWYrnW6ckYHSeaAkW0wkDAryl2 -B5v8aoFnQ1rFiVEMo4NGzw4UX+MelF7rxaaregmKVTPiqCOSPJ1McC1dHFN533FY -Wh/RVLKWo6npu+owtwYFQW+zyQhKzSIMvNujFRzhIxzxR9Gn87MoLAyfgKEzrbbT -DhqqNXTxS4UMUKCQaO93TzetX/EBrRpJj+vP640yio80h4Dr5pAd7+LnKwgpTDk1 -G88bBXJAcPZnTSKu9I2c6KY4iRNbvRz4i+ZdwwZtdW4nSdl2792L7Sl7Nc44uLL/ -ZqkKDXEBF6lsX5XpABwyK89S/SbHOytXv9o4puv+65Ac5/UShspQTMSKGZgvDauU -cs8kE1U9dPOqVNCYq9Nfwinkf6RxV1k1+gwtclxQuY7UpKXP0hNAXjAiA5KS5Crq -7aaJg9q2F4bub0mNU6n7UI6vXguF2n4SEtzPRk6RP+4TiT3bZUsmr+1ktogyOJCc -Ha8G5VdL+NBIYQthOcieYCBnTeIH7D3Sp6FYQTYtVbKFzmMK+36ERreL/wARAQAB -tD1TeWx2ZXN0cmUgTGVkcnUgLSBEZWJpYW4gTExWTSBwYWNrYWdlcyA8c3lsdmVz -dHJlQGRlYmlhbi5vcmc+iQI4BBMBAgAiBQJRPZQsAhsDBgsJCAcDAgYVCAIJCgsE -FgIDAQIeAQIXgAAKCRAVz00Yr090Ibx+EADArS/hvkDF8juWMXxh17CgR0WZlHCC -9CTBWkg5a0bNN/3bb97cPQt/vIKWjQtkQpav6/5JTVCSx2riL4FHYhH0iuo4iAPR -udC7Cvg8g7bSPrKO6tenQZNvQm+tUmBHgFiMBJi92AjZ/Qn1Shg7p9ITivFxpLyX -wpmnF1OKyI2Kof2rm4BFwfSWuf8Fvh7kDMRLHv+MlnK/7j/BNpKdozXxLcwoFBmn -l0WjpAH3OFF7Pvm1LJdf1DjWKH0Dc3sc6zxtmBR/KHHg6kK4BGQNnFKujcP7TVdv -gMYv84kun14pnwjZcqOtN3UJtcx22880DOQzinoMs3Q4w4o05oIF+sSgHViFpc3W -R0v+RllnH05vKZo+LDzc83DQVrdwliV12eHxrMQ8UYg88zCbF/cHHnlzZWAJgftg -hB08v1BKPgYRUzwJ6VdVqXYcZWEaUJmQAPuAALyZESw94hSo28FAn0/gzEc5uOYx -K+xG/lFwgAGYNb3uGM5m0P6LVTfdg6vDwwOeTNIExVk3KVFXeSQef2ZMkhwA7wya -KJptkb62wBHFE+o9TUdtMCY6qONxMMdwioRE5BYNwAsS1PnRD2+jtlI0DzvKHt7B -MWd8hnoUKhMeZ9TNmo+8CpsAtXZcBho0zPGz/R8NlJhAWpdAZ1CmcPo83EW86Yq7 -BxQUKnNHcwj2ebkCDQRRPZQsARAA4jxYmbTHwmMjqSizlMJYNuGOpIidEdx9zQ5g -zOr431/VfWq4S+VhMDhs15j9lyml0y4ok215VRFwrAREDg6UPMr7ajLmBQGau0Fc -bvZJ90l4NjXp5p0NEE/qOb9UEHT7EGkEhaZ1ekkWFTWCgsy7rRXfZLxB6sk7pzLC -DshyW3zjIakWAnpQ5j5obiDy708pReAuGB94NSyb1HoW/xGsGgvvCw4r0w3xPStw -F1PhmScE6NTBIfLliea3pl8vhKPlCh54Hk7I8QGjo1ETlRP4Qll1ZxHJ8u25f/ta -RES2Aw8Hi7j0EVcZ6MT9JWTI83yUcnUlZPZS2HyeWcUj+8nUC8W4N8An+aNps9l/ -21inIl2TbGo3Yn1JQLnA1YCoGwC34g8QZTJhElEQBN0X29ayWW6OdFx8MDvllbBV -ymmKq2lK1U55mQTfDli7S3vfGz9Gp/oQwZ8bQpOeUkc5hbZszYwP4RX+68xDPfn+ -M9udl+qW9wu+LyePbW6HX90LmkhNkkY2ZzUPRPDHZANU5btaPXc2H7edX4y4maQa -xenqD0lGh9LGz/mps4HEZtCI5CY8o0uCMF3lT0XfXhuLksr7Pxv57yue8LLTItOJ -d9Hmzp9G97SRYYeqU+8lyNXtU2PdrLLq7QHkzrsloG78lCpQcalHGACJzrlUWVP/ -fN3Ht3kAEQEAAYkCHwQYAQIACQUCUT2ULAIbDAAKCRAVz00Yr090IbhWEADbr50X -OEXMIMGRLe+YMjeMX9NG4jxs0jZaWHc/WrGR+CCSUb9r6aPXeLo+45949uEfdSsB -pbaEdNWxF5Vr1CSjuO5siIlgDjmT655voXo67xVpEN4HhMrxugDJfCa6z97P0+ML -PdDxim57uNqkam9XIq9hKQaurxMAECDPmlEXI4QT3eu5qw5/knMzDMZj4Vi6hovL -wvvAeLHO/jsyfIdNmhBGU2RWCEZ9uo/MeerPHtRPfg74g+9PPfP6nyHD2Wes6yGd -oVQwtPNAQD6Cj7EaA2xdZYLJ7/jW6yiPu98FFWP74FN2dlyEA2uVziLsfBrgpS4l -tVOlrO2YzkkqUGrybzbLpj6eeHx+Cd7wcjI8CalsqtL6cG8cUEjtWQUHyTbQWAgG -5VPEgIAVhJ6RTZ26i/G+4J8neKyRs4vz+57UGwY6zI4AB1ZcWGEE3Bf+CDEDgmnP -LSwbnHefK9IljT9XU98PelSryUO/5UPw7leE0akXKB4DtekToO226px1VnGp3Bov -1GBGvpHvL2WizEwdk+nfk8LtrLzej+9FtIcq3uIrYnsac47Pf7p0otcFeTJTjSq3 -krCaoG4Hx0zGQG2ZFpHrSrZTVy6lxvIdfi0beMgY6h78p6M9eYZHQHc02DjFkQXN -bXb5c6gCHESH5PXwPU4jQEE7Ib9J6sbk7ZT2Mw== -=j+4q ------END PGP PUBLIC KEY BLOCK----- diff --git a/jsquery/travis/pg-travis-test.sh b/jsquery/travis/pg-travis-test.sh deleted file mode 100644 index 1c192aba95..0000000000 --- a/jsquery/travis/pg-travis-test.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -set -eux - -sudo apt-get update - - -# required packages -apt_packages="postgresql-$PG_VER postgresql-server-dev-$PG_VER postgresql-common build-essential flex bison" - -# exit code -status=0 - -# pg_config path -pg_ctl_path=/usr/lib/postgresql/$PG_VER/bin/pg_ctl -initdb_path=/usr/lib/postgresql/$PG_VER/bin/initdb -config_path=/usr/lib/postgresql/$PG_VER/bin/pg_config - - -# bug: http://www.postgresql.org/message-id/20130508192711.GA9243@msgid.df7cb.de -sudo update-alternatives --remove-all postmaster.1.gz - -# stop all existing instances (because of https://github.com/travis-ci/travis-cookbooks/pull/221) -sudo service postgresql stop -# ... and make sure they don't come back -echo 'exit 0' | sudo tee /etc/init.d/postgresql -sudo chmod a+x /etc/init.d/postgresql - -# install required packages -sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y install -qq $apt_packages - - -# perform code analysis if necessary -if [ $CHECK_CODE = "true" ]; then - - if [ "$CC" = "clang" ]; then - sudo apt-get -y install -qq clang-$LLVM_VER - - scan-build-$LLVM_VER --status-bugs \ - -disable-checker deadcode.DeadStores \ - make USE_PGXS=1 USE_ASSERT_CHECKING=1 PG_CONFIG=$config_path || status=$? - exit $status - - elif [ "$CC" = "gcc" ]; then - sudo apt-get -y install -qq cppcheck - - cppcheck --template "{file} ({line}): {severity} ({id}): {message}" \ - --enable=warning,portability,performance \ - --suppress=redundantAssignment \ - --suppress=uselessAssignmentPtrArg \ - --suppress=incorrectStringBooleanError \ - --std=c89 *.c *.h 2> cppcheck.log - - if [ -s cppcheck.log ]; then - cat cppcheck.log - status=1 # error - fi - - exit $status - fi - - # don't forget to "make clean" - make clean USE_PGXS=1 PG_CONFIG=$config_path -fi - - -# create cluster 'test' -CLUSTER_PATH=$(pwd)/test_cluster -$initdb_path -D $CLUSTER_PATH -U $USER -A trust - -# build jsquery (using CFLAGS_SL for gcov) -make USE_PGXS=1 PG_CONFIG=$config_path CFLAGS_SL="$($config_path --cflags_sl) -coverage" -sudo make install USE_PGXS=1 PG_CONFIG=$config_path - -# check build -status=$? -if [ $status -ne 0 ]; then exit $status; fi - -# set permission to write postgres locks -sudo chown $USER /var/run/postgresql/ - -# start cluster 'test' -echo "port = 55435" >> $CLUSTER_PATH/postgresql.conf -$pg_ctl_path -D $CLUSTER_PATH start -l postgres.log -w - -# run regression tests -PGPORT=55435 PGUSER=$USER PG_CONFIG=$config_path make installcheck USE_PGXS=1 || status=$? - -# show diff if it exists -if test -f regression.diffs; then cat regression.diffs; fi - -#generate *.gcov files -gcov *.c *.h - -exit $status diff --git a/jsquery/travis/postgresql.gpg.key b/jsquery/travis/postgresql.gpg.key deleted file mode 100644 index 8480576ece..0000000000 --- a/jsquery/travis/postgresql.gpg.key +++ /dev/null @@ -1,77 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBE6XR8IBEACVdDKT2HEH1IyHzXkb4nIWAY7echjRxo7MTcj4vbXAyBKOfjja -UrBEJWHN6fjKJXOYWXHLIYg0hOGeW9qcSiaa1/rYIbOzjfGfhE4x0Y+NJHS1db0V -G6GUj3qXaeyqIJGS2z7m0Thy4Lgr/LpZlZ78Nf1fliSzBlMo1sV7PpP/7zUO+aA4 -bKa8Rio3weMXQOZgclzgeSdqtwKnyKTQdXY5MkH1QXyFIk1nTfWwyqpJjHlgtwMi -c2cxjqG5nnV9rIYlTTjYG6RBglq0SmzF/raBnF4Lwjxq4qRqvRllBXdFu5+2pMfC -IZ10HPRdqDCTN60DUix+BTzBUT30NzaLhZbOMT5RvQtvTVgWpeIn20i2NrPWNCUh -hj490dKDLpK/v+A5/i8zPvN4c6MkDHi1FZfaoz3863dylUBR3Ip26oM0hHXf4/2U -A/oA4pCl2W0hc4aNtozjKHkVjRx5Q8/hVYu+39csFWxo6YSB/KgIEw+0W8DiTII3 -RQj/OlD68ZDmGLyQPiJvaEtY9fDrcSpI0Esm0i4sjkNbuuh0Cvwwwqo5EF1zfkVj -Tqz2REYQGMJGc5LUbIpk5sMHo1HWV038TWxlDRwtOdzw08zQA6BeWe9FOokRPeR2 -AqhyaJJwOZJodKZ76S+LDwFkTLzEKnYPCzkoRwLrEdNt1M7wQBThnC5z6wARAQAB -tBxQb3N0Z3JlU1FMIERlYmlhbiBSZXBvc2l0b3J5iQJOBBMBCAA4AhsDBQsJCAcD -BRUKCQgLBRYCAwEAAh4BAheAFiEEuXsK/KoaR/BE8kSgf8x9RqzMTPgFAlhtCD8A -CgkQf8x9RqzMTPgECxAAk8uL+dwveTv6eH21tIHcltt8U3Ofajdo+D/ayO53LiYO -xi27kdHD0zvFMUWXLGxQtWyeqqDRvDagfWglHucIcaLxoxNwL8+e+9hVFIEskQAY -kVToBCKMXTQDLarz8/J030Pmcv3ihbwB+jhnykMuyyNmht4kq0CNgnlcMCdVz0d3 -z/09puryIHJrD+A8y3TD4RM74snQuwc9u5bsckvRtRJKbP3GX5JaFZAqUyZNRJRJ -Tn2OQRBhCpxhlZ2afkAPFIq2aVnEt/Ie6tmeRCzsW3lOxEH2K7MQSfSu/kRz7ELf -Cz3NJHj7rMzC+76Rhsas60t9CjmvMuGONEpctijDWONLCuch3Pdj6XpC+MVxpgBy -2VUdkunb48YhXNW0jgFGM/BFRj+dMQOUbY8PjJjsmVV0joDruWATQG/M4C7O8iU0 -B7o6yVv4m8LDEN9CiR6r7H17m4xZseT3f+0QpMe7iQjz6XxTUFRQxXqzmNnloA1T -7VjwPqIIzkj/u0V8nICG/ktLzp1OsCFatWXh7LbU+hwYl6gsFH/mFDqVxJ3+DKQi -vyf1NatzEwl62foVjGUSpvh3ymtmtUQ4JUkNDsXiRBWczaiGSuzD9Qi0ONdkAX3b -ewqmN4TfE+XIpCPxxHXwGq9Rv1IFjOdCX0iG436GHyTLC1tTUIKF5xV4Y0+cXIOI -RgQQEQgABgUCTpdI7gAKCRDFr3dKWFELWqaPAKD1TtT5c3sZz92Fj97KYmqbNQZP -+ACfSC6+hfvlj4GxmUjp1aepoVTo3weJAhwEEAEIAAYFAk6XSQsACgkQTFprqxLS -p64F8Q//cCcutwrH50UoRFejg0EIZav6LUKejC6kpLeubbEtuaIH3r2zMblPGc4i -+eMQKo/PqyQrceRXeNNlqO6/exHozYi2meudxa6IudhwJIOn1MQykJbNMSC2sGUp -1W5M1N5EYgt4hy+qhlfnD66LR4G+9t5FscTJSy84SdiOuqgCOpQmPkVRm1HX5X1+ -dmnzMOCk5LHHQuiacV0qeGO7JcBCVEIDr+uhU1H2u5GPFNHm5u15n25tOxVivb94 -xg6NDjouECBH7cCVuW79YcExH/0X3/9G45rjdHlKPH1OIUJiiX47OTxdG3dAbB4Q -fnViRJhjehFscFvYWSqXo3pgWqUsEvv9qJac2ZEMSz9x2mj0ekWxuM6/hGWxJdB+ -+985rIelPmc7VRAXOjIxWknrXnPCZAMlPlDLu6+vZ5BhFX0Be3y38f7GNCxFkJzl -hWZ4Cj3WojMj+0DaC1eKTj3rJ7OJlt9S9xnO7OOPEUTGyzgNIDAyCiu8F4huLPaT -ape6RupxOMHZeoCVlqx3ouWctelB2oNXcxxiQ/8y+21aHfD4n/CiIFwDvIQjl7dg -mT3u5Lr6yxuosR3QJx1P6rP5ZrDTP9khT30t+HZCbvs5Pq+v/9m6XDmi+NlU7Zuh -Ehy97tL3uBDgoL4b/5BpFL5U9nruPlQzGq1P9jj40dxAaDAX/WKJAj0EEwEIACcC -GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlB5KywFCQPDFt8ACgkQf8x9RqzM -TPhuCQ//QAjRSAOCQ02qmUAikT+mTB6baOAakkYq6uHbEO7qPZkv4E/M+HPIJ4wd -nBNeSQjfvdNcZBA/x0hr5EMcBneKKPDj4hJ0panOIRQmNSTThQw9OU351gm3YQct -AMPRUu1fTJAL/AuZUQf9ESmhyVtWNlH/56HBfYjE4iVeaRkkNLJyX3vkWdJSMwC/ -LO3Lw/0M3R8itDsm74F8w4xOdSQ52nSRFRh7PunFtREl+QzQ3EA/WB4AIj3VohIG -kWDfPFCzV3cyZQiEnjAe9gG5pHsXHUWQsDFZ12t784JgkGyO5wT26pzTiuApWM3k -/9V+o3HJSgH5hn7wuTi3TelEFwP1fNzI5iUUtZdtxbFOfWMnZAypEhaLmXNkg4zD -kH44r0ss9fR0DAgUav1a25UnbOn4PgIEQy2fgHKHwRpCy20d6oCSlmgyWsR40EPP -YvtGq49A2aK6ibXmdvvFT+Ts8Z+q2SkFpoYFX20mR2nsF0fbt1lfH65P64dukxeR -GteWIeNakDD40bAAOH8+OaoTGVBJ2ACJfLVNM53PEoftavAwUYMrR910qvwYfd/4 -6rh46g1Frr9SFMKYE9uvIJIgDsQB3QBp71houU4H55M5GD8XURYs+bfiQpJG1p7e -B8e5jZx1SagNWc4XwL2FzQ9svrkbg1Y+359buUiP7T6QXX2zY++JAj0EEwEIACcC -GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlEqbZUFCQg2wEEACgkQf8x9RqzM -TPhFMQ//WxAfKMdpSIA9oIC/yPD/dJpY/+DyouOljpE6MucMy/ArBECjFTBwi/j9 -NYM4ynAk34IkhuNexc1i9/05f5RM6+riLCLgAOsADDbHD4miZzoSxiVr6GQ3YXMb -OGld9kV9Sy6mGNjcUov7iFcf5Hy5w3AjPfKuR9zXswyfzIU1YXObiiZT38l55pp/ -BSgvGVQsvbNjsff5CbEKXS7q3xW+WzN0QWF6YsfNVhFjRGj8hKtHvwKcA02wwjLe -LXVTm6915ZUKhZXUFc0vM4Pj4EgNswH8Ojw9AJaKWJIZmLyW+aP+wpu6YwVCicxB -Y59CzBO2pPJDfKFQzUtrErk9irXeuCCLesDyirxJhv8o0JAvmnMAKOLhNFUrSQ2m -+3EnF7zhfz70gHW+EG8X8mL/EN3/dUM09j6TVrjtw43RLxBzwMDeariFF9yC+5bL -tnGgxjsB9Ik6GV5v34/NEEGf1qBiAzFmDVFRZlrNDkq6gmpvGnA5hUWNr+y0i01L -jGyaLSWHYjgw2UEQOqcUtTFK9MNzbZze4mVaHMEz9/aMfX25R6qbiNqCChveIm8m -Yr5Ds2zdZx+G5bAKdzX7nx2IUAxFQJEE94VLSp3npAaTWv3sHr7dR8tSyUJ9poDw -gw4W9BIcnAM7zvFYbLF5FNggg/26njHCCN70sHt8zGxKQINMc6SJAj0EEwEIACcC -GwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlLpFRkFCQ6EJy0ACgkQf8x9RqzM -TPjOZA//Zp0e25pcvle7cLc0YuFr9pBv2JIkLzPm83nkcwKmxaWayUIG4Sv6pH6h -m8+S/CHQij/yFCX+o3ngMw2J9HBUvafZ4bnbI0RGJ70GsAwraQ0VlkIfg7GUw3Tz -voGYO42rZTru9S0K/6nFP6D1HUu+U+AsJONLeb6oypQgInfXQExPZyliUnHdipei -4WR1YFW6sjSkZT/5C3J1wkAvPl5lvOVthI9Zs6bZlJLZwusKxU0UM4Btgu1Sf3nn -JcHmzisixwS9PMHE+AgPWIGSec/N27a0KmTTvImV6K6nEjXJey0K2+EYJuIBsYUN -orOGBwDFIhfRk9qGlpgt0KRyguV+AP5qvgry95IrYtrOuE7307SidEbSnvO5ezNe -mE7gT9Z1tM7IMPfmoKph4BfpNoH7aXiQh1Wo+ChdP92hZUtQrY2Nm13cmkxYjQ4Z -gMWfYMC+DA/GooSgZM5i6hYqyyfAuUD9kwRN6BqTbuAUAp+hCWYeN4D88sLYpFh3 -paDYNKJ+Gf7Yyi6gThcV956RUFDH3ys5Dk0vDL9NiWwdebWfRFbzoRM3dyGP889a -OyLzS3mh6nHzZrNGhW73kslSQek8tjKrB+56hXOnb4HaElTZGDvD5wmrrhN94kby -Gtz3cydIohvNO9d90+29h0eGEDYti7j7maHkBKUAwlcPvMg5m3Y= -=DA1T ------END PGP PUBLIC KEY BLOCK----- From 24b44272242bb0f959007d22ec12686ef4f4e61e Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Mon, 18 Jul 2022 13:58:14 +0300 Subject: [PATCH 13/14] Add jsquery as submodule --- .gitmodules | 3 +++ jsquery | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 jsquery diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..d656f6da67 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "jsquery"] + path = jsquery + url = https://github.com/postgrespro/jsquery.git diff --git a/jsquery b/jsquery new file mode 160000 index 0000000000..cdcfd38ae3 --- /dev/null +++ b/jsquery @@ -0,0 +1 @@ +Subproject commit cdcfd38ae3c25f9a918fdb1809a2cc2dd571b02a From d4bc6b408baf3f104ebfb11acdb8c58b5174ebca Mon Sep 17 00:00:00 2001 From: Nikita Arinkin Date: Tue, 21 May 2024 16:29:57 +0300 Subject: [PATCH 14/14] Update postgres from 14.4 to 14.12 --- Dockerfile | 43 +++++++++++---------- docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++++++++++ docker-entrypoint.sh | 82 +++++++++++++++++++++++------------------ jsquery | 2 +- 4 files changed, 141 insertions(+), 57 deletions(-) create mode 100644 docker-ensure-initdb.sh diff --git a/Dockerfile b/Dockerfile index 15b22df595..621986cc59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,16 +6,6 @@ FROM debian:bullseye-slim -RUN set -ex; \ - if ! command -v gpg > /dev/null; then \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - gnupg \ - dirmngr \ - ; \ - rm -rf /var/lib/apt/lists/*; \ - fi - # explicitly set user/group IDs RUN set -eux; \ groupadd -r postgres --gid=999; \ @@ -26,9 +16,20 @@ RUN set -eux; \ mkdir -p /var/lib/postgresql; \ chown -R postgres:postgres /var/lib/postgresql +RUN set -ex; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gnupg \ +# https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER +# https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 +# (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) + less \ + ; \ + rm -rf /var/lib/apt/lists/* + # grab gosu for easy step-down from root # https://github.com/tianon/gosu/releases -ENV GOSU_VERSION 1.14 +ENV GOSU_VERSION 1.17 RUN set -eux; \ savedAptMark="$(apt-mark showmanual)"; \ apt-get update; \ @@ -58,7 +59,9 @@ RUN set -eux; \ ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ fi; \ apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ - localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 + echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ + locale-gen; \ + locale -a | grep 'en_US.utf8' ENV LANG en_US.utf8 RUN set -eux; \ @@ -81,13 +84,13 @@ RUN set -ex; \ mkdir -p /usr/local/share/keyrings/; \ gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ - command -v gpgconf > /dev/null && gpgconf --kill all; \ + gpgconf --kill all; \ rm -rf "$GNUPGHOME" ENV PG_MAJOR 14 ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin -ENV PG_VERSION 14.4-1.pgdg110+1 +ENV PG_VERSION 14.12-1.pgdg110+1 RUN set -ex; \ \ @@ -97,7 +100,7 @@ RUN set -ex; \ dpkgArch="$(dpkg --print-architecture)"; \ aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main $PG_MAJOR"; \ case "$dpkgArch" in \ - amd64 | arm64 | ppc64el) \ + amd64 | arm64 | ppc64el | s390x) \ # arches officialy built by upstream echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ apt-get update; \ @@ -178,11 +181,11 @@ RUN set -eux; \ sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample -RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql +RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 3777 /var/run/postgresql ENV PGDATA /var/lib/postgresql/data -# this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) -RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" +# this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) +RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data COPY jsquery/ /opt/jsquery/ @@ -192,8 +195,8 @@ RUN apt-get update && apt-get install -y build-essential bison flex postgresql-s RUN cd /opt/jsquery \ && make USE_PGXS=1 \ && make USE_PGXS=1 install - -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/docker-ensure-initdb.sh b/docker-ensure-initdb.sh new file mode 100644 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 1896cd85c5..6f59993e08 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -11,7 +11,7 @@ file_env() { local fileVar="${var}_FILE" local def="${2:-}" if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar" exit 1 fi local val="$def" @@ -38,11 +38,11 @@ docker_create_db_directories() { mkdir -p "$PGDATA" # ignore failure since there are cases where we can't chmod (and PostgreSQL might fail later anyhow - it's picky about permissions of this directory) - chmod 700 "$PGDATA" || : + chmod 00700 "$PGDATA" || : # ignore failure since it will be fine when using the image provided directory; see also https://github.com/docker-library/postgres/pull/289 mkdir -p /var/run/postgresql || : - chmod 775 /var/run/postgresql || : + chmod 03775 /var/run/postgresql || : # Create the transaction log directory before initdb is run so the directory is owned by the correct user if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then @@ -77,8 +77,8 @@ docker_init_database_dir() { NSS_WRAPPER_GROUP="$(mktemp)" export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP local gid; gid="$(id -g)" - echo "postgres:x:$uid:$gid:PostgreSQL:$PGDATA:/bin/false" > "$NSS_WRAPPER_PASSWD" - echo "postgres:x:$gid:" > "$NSS_WRAPPER_GROUP" + printf 'postgres:x:%s:%s:PostgreSQL:%s:/bin/false\n' "$uid" "$gid" "$PGDATA" > "$NSS_WRAPPER_PASSWD" + printf 'postgres:x:%s:\n' "$gid" > "$NSS_WRAPPER_GROUP" break fi done @@ -88,7 +88,8 @@ docker_init_database_dir() { set -- --waldir "$POSTGRES_INITDB_WALDIR" "$@" fi - eval 'initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"' + # --pwfile refuses to handle a properly-empty file (hence the "\n"): https://github.com/docker-library/postgres/issues/1025 + eval 'initdb --username="$POSTGRES_USER" --pwfile=<(printf "%s\n" "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"' # unset/cleanup "nss_wrapper" bits if [[ "${LD_PRELOAD:-}" == */libnss_wrapper.so ]]; then @@ -102,20 +103,24 @@ docker_init_database_dir() { # print large warning if POSTGRES_HOST_AUTH_METHOD is set to 'trust' # assumes database is not set up, ie: [ -z "$DATABASE_ALREADY_EXISTS" ] docker_verify_minimum_env() { - # check password first so we can output the warning before postgres - # messes it up - if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then - cat >&2 <<-'EOWARN' + case "${PG_MAJOR:-}" in + 12 | 13) # https://github.com/postgres/postgres/commit/67a472d71c98c3d2fa322a1b4013080b20720b98 + # check password first so we can output the warning before postgres + # messes it up + if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then + cat >&2 <<-'EOWARN' - WARNING: The supplied POSTGRES_PASSWORD is 100+ characters. + WARNING: The supplied POSTGRES_PASSWORD is 100+ characters. - This will not work if used via PGPASSWORD with "psql". + This will not work if used via PGPASSWORD with "psql". - https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412) - https://github.com/docker-library/postgres/issues/507 + https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412) + https://github.com/docker-library/postgres/issues/507 - EOWARN - fi + EOWARN + fi + ;; + esac if [ -z "$POSTGRES_PASSWORD" ] && [ 'trust' != "$POSTGRES_HOST_AUTH_METHOD" ]; then # The - option suppresses leading tabs but *not* spaces. :) cat >&2 <<-'EOE' @@ -157,7 +162,7 @@ docker_process_init_files() { # psql here for backwards compatibility "${psql[@]}" psql=( docker_process_sql ) - echo + printf '\n' local f for f; do case "$f" in @@ -165,20 +170,20 @@ docker_process_init_files() { # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936 # https://github.com/docker-library/postgres/pull/452 if [ -x "$f" ]; then - echo "$0: running $f" + printf '%s: running %s\n' "$0" "$f" "$f" else - echo "$0: sourcing $f" + printf '%s: sourcing %s\n' "$0" "$f" . "$f" fi ;; - *.sql) echo "$0: running $f"; docker_process_sql -f "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;; - *.sql.xz) echo "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;; - *.sql.zst) echo "$0: running $f"; zstd -dc "$f" | docker_process_sql; echo ;; - *) echo "$0: ignoring $f" ;; + *.sql) printf '%s: running %s\n' "$0" "$f"; docker_process_sql -f "$f"; printf '\n' ;; + *.sql.gz) printf '%s: running %s\n' "$0" "$f"; gunzip -c "$f" | docker_process_sql; printf '\n' ;; + *.sql.xz) printf '%s: running %s\n' "$0" "$f"; xzcat "$f" | docker_process_sql; printf '\n' ;; + *.sql.zst) printf '%s: running %s\n' "$0" "$f"; zstd -dc "$f" | docker_process_sql; printf '\n' ;; + *) printf '%s: ignoring %s\n' "$0" "$f" ;; esac - echo + printf '\n' done } @@ -209,7 +214,7 @@ docker_setup_db() { POSTGRES_DB= docker_process_sql --dbname postgres --set db="$POSTGRES_DB" <<-'EOSQL' CREATE DATABASE :"db" ; EOSQL - echo + printf '\n' fi } @@ -224,6 +229,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' @@ -243,12 +249,12 @@ pg_setup_hba_conf() { auth="$(postgres -C password_encryption "$@")" : "${POSTGRES_HOST_AUTH_METHOD:=$auth}" { - echo + printf '\n' if [ 'trust' = "$POSTGRES_HOST_AUTH_METHOD" ]; then - echo '# warning trust is enabled for all connections' - echo '# see https://www.postgresql.org/docs/12/auth-trust.html' + printf '# warning trust is enabled for all connections\n' + printf '# see https://www.postgresql.org/docs/12/auth-trust.html\n' fi - echo "host all all all $POSTGRES_HOST_AUTH_METHOD" + printf 'host all all all %s\n' "$POSTGRES_HOST_AUTH_METHOD" } >> "$PGDATA/pg_hba.conf" } @@ -328,13 +334,17 @@ _main() { docker_temp_server_stop unset PGPASSWORD - echo - echo 'PostgreSQL init process complete; ready for start up.' - echo + cat <<-'EOM' + + PostgreSQL init process complete; ready for start up. + + EOM else - echo - echo 'PostgreSQL Database directory appears to contain a database; Skipping initialization' - echo + cat <<-'EOM' + + PostgreSQL Database directory appears to contain a database; Skipping initialization + + EOM fi fi diff --git a/jsquery b/jsquery index cdcfd38ae3..9583d5b691 160000 --- a/jsquery +++ b/jsquery @@ -1 +1 @@ -Subproject commit cdcfd38ae3c25f9a918fdb1809a2cc2dd571b02a +Subproject commit 9583d5b6914b5d89483ced4fcee428d5fccbe3c2