Completed
Push — master ( 87411f...fc87fb )
by Nicolas
02:23
created

lib/Elastica/Tool/CrossIndex.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Elastica\Tool;
3
4
use Elastica\Bulk;
5
use Elastica\Bulk\Action;
6
use Elastica\Index;
7
use Elastica\Query\MatchAll;
8
use Elastica\Scroll;
9
use Elastica\Type;
10
11
/**
12
 * Functions to move documents and types between indices.
13
 *
14
 * @author Manuel Andreo Garcia <[email protected]>
15
 *
16
 * @deprecated use Reindex instead. This class will be removed in further Elastica releases.
17
 */
18
class CrossIndex
19
{
20
    /**
21
     * Type option.
22
     *
23
     * type: string | string[] | \Elastica\Type | \Elastica\Type[] | null
24
     * default: null (means all types)
25
     */
26
    const OPTION_TYPE = 'type';
27
28
    /**
29
     * Query option.
30
     *
31
     * type: see \Elastica\Query::create()
32
     * default: Elastica\Query\MatchAll
33
     */
34
    const OPTION_QUERY = 'query';
35
36
    /**
37
     * Expiry time option.
38
     *
39
     * type: string (see Elastica\Scroll)
40
     * default: '1m'
41
     */
42
    const OPTION_EXPIRY_TIME = 'expiryTime';
43
44
    /**
45
     * Size per shard option.
46
     *
47
     * type: int (see Elastica\Scroll)
48
     * default: 1000
49
     */
50
    const OPTION_SIZE_PER_SHARD = 'sizePerShard';
51
52
    /**
53
     * Reindex documents from an old index to a new index.
54
     *
55
     * @link https://www.elastic.co/guide/en/elasticsearch/guide/master/reindex.html
56
     *
57
     * @param \Elastica\Index $oldIndex
58
     * @param \Elastica\Index $newIndex
59
     * @param array           $options  keys: CrossIndex::OPTION_* constants
60
     *
61
     * @return \Elastica\Index The new index object
62
     */
63
    public static function reindex(
64
        Index $oldIndex,
65
        Index $newIndex,
66
        array $options = []
67
    ) {
68
        // prepare search
69
        $search = $oldIndex->createSearch();
70
71
        $options = array_merge(
72
            [
73
                self::OPTION_TYPE => null,
74
                self::OPTION_QUERY => new MatchAll(),
75
                self::OPTION_EXPIRY_TIME => '1m',
76
                self::OPTION_SIZE_PER_SHARD => 1000,
77
            ],
78
            $options
79
        );
80
81
        if (isset($options[self::OPTION_TYPE])) {
82
            $type = $options[self::OPTION_TYPE];
83
            $search->addTypes(is_array($type) ? $type : [$type]);
84
        }
85
        $search->setQuery($options[self::OPTION_QUERY]);
86
87
        // search on old index and bulk insert in new index
88
        $scroll = new Scroll(
89
            $search,
90
            $options[self::OPTION_EXPIRY_TIME]
91
        );
92
        foreach ($scroll as $resultSet) {
93
            $bulk = new Bulk($newIndex->getClient());
94
            $bulk->setIndex($newIndex);
95
96
            foreach ($resultSet as $result) {
0 ignored issues
show
The expression $resultSet of type object<Elastica\ResultSet>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
97
                $action = new Action();
98
                $action->setType($result->getType());
99
                $action->setId($result->getId());
100
                $action->setSource($result->getData());
101
102
                $bulk->addAction($action);
103
            }
104
105
            $bulk->send();
106
        }
107
108
        $newIndex->refresh();
109
110
        return $newIndex;
111
    }
112
113
    /**
114
     * Copies type mappings and documents from an old index to a new index.
115
     *
116
     * @see \Elastica\Tool\CrossIndex::reindex()
117
     *
118
     * @param \Elastica\Index $oldIndex
119
     * @param \Elastica\Index $newIndex
120
     * @param array           $options  keys: CrossIndex::OPTION_* constants
121
     *
122
     * @return \Elastica\Index The new index object
123
     */
124
    public static function copy(
125
        Index $oldIndex,
126
        Index $newIndex,
127
        array $options = []
128
    ) {
129
        // normalize types to array of string
130
        $types = [];
131
        if (isset($options[self::OPTION_TYPE])) {
132
            $types = $options[self::OPTION_TYPE];
133
            $types = is_array($types) ? $types : [$types];
134
135
            $types = array_map(
136
                function ($type) {
137
                    if ($type instanceof Type) {
138
                        $type = $type->getName();
139
                    }
140
141
                    return (string) $type;
142
                },
143
                $types
144
            );
145
        }
146
147
        // copy mapping
148
        foreach ($oldIndex->getMapping() as $type => $mapping) {
149
            if (!empty($types) && !in_array($type, $types, true)) {
150
                continue;
151
            }
152
153
            $type = new Type($newIndex, $type);
154
            $type->setMapping($mapping['properties']);
155
        }
156
157
        // copy documents
158
        return self::reindex($oldIndex, $newIndex, $options);
159
    }
160
}
161