Полнотекстовый поиск с Xapian и PHP

Метки: веб-разработка, php, xapian, mysql

Fulltext searches with Xapian and PHP Fulltext searches with Xapian and PHP

Иногда MySQL просто не достаточно быстрый. Особенно когда дело доходит до полнотекстового поиска. Все индексы должны быть корректно расставлены, а если мы берем разные поля у которых отличается длина для определения соотношения релевантности, то вещи очень скоро становятся весьма сложными. На помощь приходит Xapian.

Что такое Xapian?
Xapian — это библиотека поискового механизма, схожая с Lucene и Sphinx. Скомпилирована из кода C++, следовательно довольно низкоуровневая. Доступны привязки к PHP, Perl и Python, которые сразу готовы к использованию. Пакеты доступны для Ubuntu и Red Hat, компилируется под OSX, а также можно запускать под Windows через CygWin.

Примеры скриптов
Вместо того чтобы объяснять что да как, я решил создать некоторые демонстрационные скрипты.

db.sql
Убрать подсветку кода
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE DATABASE `demo`;
 
CREATE TABLE `demo`.`demo` (
`id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`unique_key` VARCHAR( 255 ) NOT NULL ,
`name` VARCHAR( 255 ) NULL DEFAULT NULL ,
`summary` TEXT NULL DEFAULT NULL ,
`date` DATETIME NULL DEFAULT NULL ,
UNIQUE (`unique_key`));
 
INSERT INTO `demo`.`demo` 
(`id`, `unique_key`, `name`, `summary`, `date`)
VALUES (NULL, 'foo', 'foo', 'foo bar test', '2008-11-05 00:00:00'), 
(NULL , 'bar', 'bar', 'test foo bar', '2009-11-05 00:00:00');

XapianWrapper.php
Убрать подсветку кода
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<?php
// includes
require_once 'xapian.php';
 
// main class
class XapianWrapper {
  const XAPIAN_FIELD_URL = 0;
  const XAPIAN_FIELD_NAME = 1;
  const XAPIAN_FIELD_DATE = 2;
  const XAPIAN_FIELD_UID = 3;
  const XAPIAN_FIELD_SUMMARY = 4;
  const XAPIAN_PREFIX_UID = "UID:";
  
  const SETTINGS_XAPIAN_DB = './xapian_db';
 
  const SETTINGS_MYSQL_HOST = 'localhost';
  const SETTINGS_MYSQL_USER = 'root';
  const SETTINGS_MYSQL_PASS = 'root';
  const SETTINGS_MYSQL_DB = 'demo';
  const SETTINGS_MYSQL_TABLE = 'demo';
 
  const DEFAULT_COUNT = 10;
 
  private $mysql_link;
  private $category_cache;
  
  private $xapian_read_db;
  private $xapian_write_db;
  private $xapian_stemmer;
  private $xapian_indexer;
  private $xapian_enquire;
 
  private function xapian_init_readonly() {
    try{
      $this->xapian_read_db = new XapianDatabase(self::SETTINGS_XAPIAN_DB);
      $this->xapian_stemmer = new XapianStem("english");
      $this->xapian_enquire = new XapianEnquire($this->xapian_read_db);
    } catch(Exception $e) {
      throw new Exception('Could initialize Xapian: ' . $e->getMessage());
    } 
  }
  
  private function xapian_init_writable() {
    try{
      $this->xapian_write_db = new XapianWritableDatabase(
self::SETTINGS_XAPIAN_DB, Xapian::DB_CREATE_OR_OPEN);  
      $this->xapian_indexer = new XapianTermGenerator();
      $this->xapian_stemmer = new XapianStem("english");
      $this->xapian_indexer->set_stemmer($this->xapian_stemmer);
    } catch(Exception $e) {
      throw new Exception('Could initialize Xapian: ' . $e->getMessage());
    } 
  }
  
  private function mysql_init() {
    $this->mysql_link = mysql_connect(
self::SETTINGS_MYSQL_HOST, self::SETTINGS_MYSQL_USER, self::SETTINGS_MYSQL_PASS);
    if (!$this->mysql_link) {
      throw new Exception('Could not connect: ' . mysql_error());
    }
 
    $db_selected = mysql_select_db(self::SETTINGS_MYSQL_DB, $this->mysql_link);
    if (!$db_selected) {
      throw new Exception('Can\'t use db : ' . mysql_error());
    }
  }
  
  /**
   * Index method
   *
   */
  public function index($params) {
    $this->xapian_init_writable();
    $this->mysql_init();
    
    $start = microtime(true);
 
    $response = new stdClass();
    $response->indexed = array();
 
    $offset = (isset($params['offset'])) ? intval($params['offset']) : 0;
    $count = (isset($params['count'])) ? intval($params['count']) : self::DEFAULT_COUNT;
    $sql = 'SELECT * FROM '.
self::SETTINGS_MYSQL_TABLE.' LIMIT ' . $offset . ', ' . $count . ';';
 
    $result = mysql_query($sql);
 
    if (!$result) {
      throw new Exception('Invalid query: ' . mysql_error());
    }
    
    $this->xapian_write_db->begin_transaction();
 
    while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
       $response->indexed[] = $this->index_row($row);      
    }
 
    $this->xapian_write_db->commit_transaction();
    mysql_free_result($result);
    mysql_close($this->mysql_link);
 
    return $response;
  }
    
 
  private function index_row($row) {
    $doc = new XapianDocument();
 
    $this->xapian_indexer->set_document($doc);
    $this->xapian_indexer->index_text($row['name'],50);
    $this->xapian_indexer->index_text($row['summary'], 1);
 
    $GUID = self::XAPIAN_PREFIX_UID . $row['unique_key'];
    $doc->add_term($GUID);
 
    $doc->add_value(self::XAPIAN_FIELD_URL, $row['url']);
    $doc->add_value(self::XAPIAN_FIELD_DATE, date('Ymd', strtotime($row['date'])));
    $doc->add_value(self::XAPIAN_FIELD_UID, $row['unique_key']);
    $doc->add_value(self::XAPIAN_FIELD_NAME, $row['name']);
    $doc->add_value(self::XAPIAN_FIELD_SUMMARY, $row['summary']);
    
    $this->xapian_write_db->replace_document(strval($GUID), $doc);
 
    $row_response = array();
    $row_response['name'] = $row['name'];
    $row_response['guid'] = $row['unique_key'];
    $row_response['url'] = $row['url'];
    return $row_response; 
  }
  
  /**
   * Delete method
   *
   */
  public function delete($params) {
    $this->xapian_init_writable();
 
    $this->xapian_write_db->begin_transaction();
 
    $response = array();
 
    foreach($params['items'] as $param_guid) {      
      $GUID = self::XAPIAN_PREFIX_UID . $param_guid;
      $this->xapian_write_db->delete_document(strval($GUID));
      $response[] = $param_guid;
    }
    
    $this->xapian_write_db->commit_transaction();
    return $response;
  }
 
  /**
   * Search method
   *
   */
  public function search($params) {
    $this->xapian_init_readonly();
 
    $start = microtime(true);
 
    // queries array to later construct full query
    $arr_queries = array();
 
    // from date
    if(!empty($params['date_from'])) {
      $arr_queries[] = new XapianQuery(
XapianQuery::OP_VALUE_GE, 6, date('Ymd', strtotime($params['date_from'])));
    }
 
    // to date
    if(!empty($params['date_to'])) {
      $arr_queries[] = new XapianQuery(
XapianQuery::OP_VALUE_LE, 6, date('Ymd', strtotime($params['date_to'])));
    }
 
    // unique key
    if(!empty($params['unique_key'])) {
      $arr_queries[] = new XapianQuery(self::XAPIAN_PREFIX_UID . $params['unique_key']);
    }
 
    // normal search query parsed
    if(!empty($params['search'])) {
      $qp = new XapianQueryParser();
      $qp->set_stemmer($this->xapian_stemmer);
      $qp->set_database($this->xapian_read_db);
      $qp->set_stemming_strategy(XapianQueryParser::STEM_SOME);
      $arr_queries[] = $qp->parse_query($params['search']);
    }
 
    // Find the results for the query.
        // construct final query
    $query = array_pop($arr_queries);
 
    foreach($arr_queries as $sq) {
      $query = new XapianQuery(XapianQuery::OP_AND, $query, $sq);
    }    
    $this->xapian_enquire->set_query($query);
  
    // set the count to the specified params
    $offset = (isset($params['offset'])) ? intval($params['offset']) : 0;
    $count = (isset($params['count'])) ? intval($params['count']) : self::DEFAULT_COUNT;
    $matches = $this->xapian_enquire->get_mset($offset, $count);
 
    $response = new stdClass();
    $response->result_count = $matches->get_matches_estimated();
    $results = array();
 
    $i = $matches->begin();
    while (!$i->equals($matches->end())) {
      $m = array();
 
      $n = $i->get_rank() + 1;
      $doc = $i->get_document();
 
      $m['position'] = $n;
      $m['url'] = $doc->get_value(self::XAPIAN_FIELD_URL);
      $m['name'] = $doc->get_value(self::XAPIAN_FIELD_NAME);
      $m['summary'] = $doc->get_value(self::XAPIAN_FIELD_SUMMARY);
      $m['date'] = $doc->get_value(self::XAPIAN_FIELD_DATE);
      $m['unique_key'] = $doc->get_value(self::XAPIAN_FIELD_UID);
      $m['percent'] = $i->get_percent();
 
      $results[count($results)] = $m;
      $i->next();
    }
 
    $response->results = $results;
    $end = microtime(true);
    
    // runtime info
    $response->execute = new stdClass();
    $response->execute->call = 'search';
    $response->execute->offset = $offset;
    $response->execute->count = $count;
    $response->execute->start = $start;
    $response->execute->end = $end;
    $response->execute->time = $end - $start;
 
    // debug stuff
    $response->execute->debug = $query->get_description();
 
    return $response;
  }
}

index.php
Убрать подсветку кода
1
2
3
4
5
6
7
<?php
 
require_once 'XapianWrapper.php';
 
$x = new XapianWrapper();
$res = $x->index(array());
print_r($res);

search.php
Убрать подсветку кода
1
2
3
4
5
6
7
8
<?php
 
require_once 'XapianWrapper.php';
 
$x = new XapianWrapper();
$params = array('search' => 'foo');
$res = $x->search($params);
print_r($res);

delete.php
Убрать подсветку кода
1
2
3
4
5
6
7
8
9
<?php
 
require_once 'XapianWrapper.php';
$x = new XapianWrapper();
$params = array(
        'items' => array('foo'),
);
$res = $x->delete($params);
print_r($res);

Запуск примера
Теперь мы должны запустить php-примеры через командную строку.
Убрать подсветку кода
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
bash$ php index.php 
stdClass Object
(
    [indexed] => Array
        (
            [0] => Array
                (
                    [name] => foo
                    [guid] => foo
                    [url] => 
                )
 
            [1] => Array
                (
                    [name] => bar
                    [guid] => bar
                    [url] => 
                )
 
        )
 
)
bash$ php search.php 
stdClass Object
(
    [result_count] => 2
    [results] => Array
        (
            [0] => Array
                (
                    [position] => 1
                    [url] => 
                    [name] => foo
                    [summary] => foo bar test
                    [date] => 20081105
                    [unique_key] => foo
                    [percent] => 100
                )
 
            [1] => Array
                (
                    [position] => 2
                    [url] => 
                    [name] => bar
                    [summary] => test foo bar
                    [date] => 20091105
                    [unique_key] => bar
                    [percent] => 50
                )
 
        )
 
    [execute] => stdClass Object
        (
            [call] => search
            [offset] => 0
            [count] => 10
            [start] => 1256674866.79
            [end] => 1256674866.79
            [time] => 0.000944852828979
            [debug] => Xapian::Query(Zfoo:(pos=1))
        )
 
)
bash$ php delete.php 
Array
(
    [0] => foo
)
bash$ php search.php 
stdClass Object
(
    [result_count] => 1
    [results] => Array
        (
            [0] => Array
                (
                    [position] => 1
                    [url] => 
                    [name] => bar
                    [summary] => test foo bar
                    [date] => 20091105
                    [unique_key] => bar
                    [percent] => 100
                )
 
        )
 
    [execute] => stdClass Object
        (
            [call] => search
            [offset] => 0
            [count] => 10
            [start] => 1256674876.02
            [end] => 1256674876.02
            [time] => 0.000872850418091
            [debug] => Xapian::Query(Zfoo:(pos=1))
        )
 
)

Все верно, я оставил вам примеры для улучшения и подстраивания под ваши личные нужды. Как обычно, любые советы по улучшению приветствуются.

Оригинал: Fulltext searches with Xapian and PHP

Рейтинг: 12345   << Вы можете поставить оценку этой статье


Подобные статьи:
   6 инструментов чтобы быть эффективным Web-разработчиком
   Понимание области видимости в объектно-ориентированном JavaScript
   Введение в искусство модульного тестирования в PHP
   Интеграция FCKeditor в Zend_Form
   Автоматизированное тестирование с использованием Zend Framework


Обсуждение статьи:

 
Сергей [2011-11-03]
А где можно взять файл xapian.php


neb0t [2012-12-13]
sudo apt-get build-dep xapian-bindings
sudo apt-get install php5-dev php5-cli devscripts
apt-get source xapian-bindings
cd xapian-bindings-1.2.*
rm -f debian/control debian/*-stamp
env PHP_VERSIONS=5 debian/rules maint
sed -i 's!include_path=php5$!include_path=$(srcdir)/php5! ' php/Makefile.in
echo auto-commit >> debian/source/options
debuild -e PHP_VERSIONS=5 -us -uc
cd ..

sudo dpkg -i php5-xapian_*.deb

в /usr/share/php/ появится xapian.php

РНР must be =>5


KennethFus [2015-06-17]
But let us just go back to those 270 fights he took part in, how many of these do Ray Ban Pink Lens Wayfarer you think Figg won Bearing in mind that he was probably in his late 40s for half of them. Well if you said anything other than 269 of them you be dead wrong and now have the ghost of a man fueled only by the desire to kill everything with his bare hands annoyed at you. Yep, in 270 fights, Figg only lost a single one, to his own student.(Low consumption of Vitamin D nutrients and consequently greater reliance on skin absorption.)Body Mass Index. (Large people have more skin and, being better insulated, tend to wear less clothing.)Latitude. (The nearer individuals live to a pole, the shorter their winter UV exposure.)Skin colour.

<a href=http://blogs.flinders.edu.au/wp-content/rayba ns.php?page=381>Prescription Ray Ban Sunglasses AU - Cheap Ray Ban Spectacles Women On Sale</a>
Like many such long standing clubs across the country, the Palos Verdes group has an extraordinary health record. In more than 30 Rayban Clubmasters Wayfarer years, Bassler says, just three members have died: one of a brain tumor, another in a plane crash, the third in a carjacking. There have been no heart attacks; no strokes; no heart trouble at all.


KennethFus [2015-06-23]
Young female athletes are more at risk of damaging the ACL than males when they compete in similar sports, suggests research by Prescription Ray Ban Aviators the National Athletic Trainers' Association and the National Institutes of Health. Among the 989,619 patients who visited doctors with ACL injuries in 2010 (the most recent numbers available), about one in four were females, according to the orthopedic surgeons group. More men play sports than women, so the numbers don't tell the whole story.

<a href=http://hybridarts.co.uk/sowtheseeds/wp-conten t/rayban.php?page=176>Black Lens Ray Ban Aviators - Online Discount Ray Ban Brown Sunglasses</a>
ConclusionCelgene's Apremilast will take the company outside its core hematology and oncology focus. The drug holds a huge market opportunity, as it has a Outlet Ray Ban Sunglasses benign side effect profile compared to the competing drugs in the market. Looking at the positive study results for Apremilast, I expect a positive result for the company from the FDA.


KennethFus [2015-06-24]
Dr. Christian K. : This certainly sounds like an arthritis situation considering there are times when she does better than others. Ray Ban Kids Sunglasses UK This is one of the fastest acting aids we could ever give for the heart, because it feeds that heart immediately. Most hearts are suffering from malnutrition because of processed food we are eating, but here it gets a good powerful dose of real food and it's something that has brought people in time after time. This is something that everyone should know how great it is, because a heart attack can come to your friends or loved ones any time.

<a href=http://3d-perception.com/news2015/index.php?p age=140>Sunglass Ray Ban 2015 - Find Best Ray-Ban New Wayfarer Sunglasses</a>
355 patients with severe Crohn's disease from the USA, Prescription Ray Ban Sunglasses Online Europe, and Israel who responded within two weeks to an initial 5 mg/kg intravenous infusion of infliximab took part in the study. They were randomly assigned repeat infusions of placebo, repeat infusions of 5 mg/kg infliximab, or 10 mg/kg infliximab (after two treatments with 5mg/kg infliximab). Treatment took place at randomisation, after one month, and thereafter every two months for a year.


KennethFus [2015-06-25]
Add to that lost productivity of more than $150 billion a year. 1964: Cigarettes were the major concern. &quot;The habitual use Ray Band Glasses Wayfarer of tobacco is related primarily to psychological and social drives, reinforced and perpetuated by pharmacological (drug) actions of nicotine.&quot; 2015: &quot;The tobacco industry continues to introduce and market new products that.

<a href=http://blogs.flinders.edu.au/wp-content/rayba ns.php?page=683>Online Glasses Ray Ban - Wayfarer Ray Ban Sunglasses Cheap Black White Orange</a>
Tortoiseshell Ray Ban Before taking devil's claw, discuss side effects, dosage and potential Ray Ban Sunglasses Australia drug interactions with your doctor. Is an herb that may be beneficial in treating arthritis, sciatica and back pain. The Memorial Sloan Kettering Cancer Center states that arnica, also known as arnica montana or mountain tobacco, is derived from the flowers and rhizome, or underground stem, of the plant.


KennethFus [2015-06-27]
Griz remain No. 7 in Sports Network pollUM's Branzburg goes 2 2 at ITA Regional fencers fare well at tournamentRachac column: Rugged and selfless, Newell a prized asset for Very Cheap Ray Bans Wayfarer BobcatsGrizzlies in the NFL: Biermann has good day against RavensPast champion leads Fall Mack Days fishing tournament on Flathead LakeScary good business: Surveys anticipate Halloween surgeDirty Fingernails: Frost will kill, not sweeten, squashProjects improve Kootenai River fishingNEIGHBORS: Darby woman has been a rebel on wheels for more than 60 yearsWell, the Senate Democrats once again display a huge lack oftesticular fortitude and quietly, hoping we won't notice, let theidea of actually making some much needed reforms in the filibusterprocedure slide off the table.Another promise broken. Sort of like the failed mortgage loanmodification program.

<a href=http://3d-perception.com/news2015/index.php?p age=79>2132 Ray Ban Wayfarers - Shop For Ray Bans 2140</a>
If somebody is able to produce that magic pill, that guy is going Ray Ban Clubmaster Sunglasses UK to turn into a billionaire overnight.&quot;That is the motivating thing that keeps these companies producing these drugs.&quot;Neither Belviq nor Qsymia is a magic pill. In fact, both have potential side effects severe enough that the FDA initially rejected them. The drugs are intended not for people who simply want to lose a few pounds but for those who meet the threshold of obesity: a body mass index of at least 30 (a person who is 6 feet tall and weighs 221 pounds has a BMI of 30), or a BMI of at least 27, along with another weight related problem such as Cheap Black Ray Ban Wayfarer high blood pressure, high cholesterol or type 2 diabetes.


KennethFus [2015-07-07]
Ray Ban Sunglasses Models George, Utah, Blaine L. (Nadine) Anderson, Draper, Utah, Mary Kay (Denny) Burgess, Lehi, Utah, Ray Ban Red Sunglasses David N. (Nola) Anderson, Monroe, Washington, Paul A. At any rate, Leah is singled out for her past relationship with Tim. &quot;Have you ever been Black Lens Ray Ban Aviators intimate with Tim&quot; Giuliana asks the question we all want to know. &quot;That's something personal between Tim and I,&quot; Leah tells the hosts.There are chances that what the individual perceives as ear pain is actually 'referred' pain', originating from some other part. For example, people often complain of sharp stabbing pain in the ear when swallowing. This is actually the Rayban Glasses UK Wayfarer referred pain triggered by the irritation of nerves connected to the ear, which are actively involved when swallowing.

<a href=http://blogs.flinders.edu.au/wp-content/rayba ns.php?page=668>Ray Ban Wayfarer Purple - Ray Band Free Shipping. New</a>
It like throwing money away,&quot; Jacob said.We put Noelle, Ryan and Hunter brand loyalty to the test to see if they could tell the difference between store brands Men Ray Ban Wayfarers and name brands. Chef Robert Gartz, of Bimini Restaurant, and Natalie Martinez, a dietician at Grand Strand Regional Medical Center, weighed in too.GREAT VALUE: $1.28Right off the bat, all of our taste testers weren too impressed with the look and feel of each brand of bread. After tasting a piece, Noelle described the Great Value loaf as &quot;tasting bad,&quot; while Ryan described it as &quot;dry.&quot;The Sunbeam bread didn fare well with our experts, either.


KennethFus [2015-07-09]
As part of their salaries, assembly members receive benefits, many of which require contributions. Health coverage includes three health maintenance organizations and three preferred provider organization, two dental plans and Ray Ban Wayfarer White two vision plans. They do not get a long term disability plan, but are entitled to group term life insurance, with supplemental life insurance available.

<a href=http://3d-perception.com/news2015/index.php?p age=134>Ray Ban Blue Wayfarer - Save 70% Off Cheap Ray Ban Usa Outlet</a>
North Shore residents are asked to join their neighbors to help find Ray Ban Parts Wayfarers a cure. Volunteers are now needed to assist the Arthritis Foundation with the seventh annual North Shore Arthritis Walk being held at Lynch Park in Beverly on Sunday, May 23. Photo Safari sessions are open to the public (pre registration for each event is required).


raybansFus [2015-07-24]
Cheap ray bans sunglasses Ray Ban RB4147 Sunglasses Brown Frame Crystal Green Gradient Len <RB>147-174] - * With slim frame and Monel construction, the Ray Ban RB4147 Sunglasses Brown Frame Crystal Green Gradient Lens is a great pair of sunglasses for traveler. These metal full rimmed Ray Ban Sunglasses with skull temple are a perfect accessory for a long drive in the sun.* Double brow bar, <a href="http://www.rbfancier.com/ray-ban-rb4147-sung lasses-brown-frame-crystal-green-gradient-len-p-20 9.html">Now buy Price Save 87%</a>


Moca [2015-10-18]
Un lloc web reeixit - una combinació de diversos factors, incloent: planificació de la qualitat, la facilitat de navegació, la informació disponible, el disseny visual. Combinació crítica de coneixements que inclou la concepció creativa i habilitats tècniques i interactius i disseny li permetrà mantenir el seu lloc web amb eficàcia. http://saitv.3dn.ru/ tecnologia d'Internet no es queda quiet, el canvi dels motors de recerca de feina, la millora del mètode dels llocs de mostreig en els resultats de cerca. Seguim les innovacions i estem disposats a donar assessorament gratuït sobre el desenvolupament i la millora del seu lloc.


Moca [2015-10-18]
Un lloc web reeixit - una combinació de diversos factors, incloent: planificació de la qualitat, la facilitat de navegació, la informació disponible, el disseny visual. Combinació crítica de coneixements que inclou la concepció creativa i habilitats tècniques i interactius i disseny li permetrà mantenir el seu lloc web amb eficàcia. http://saitv.3dn.ru/ tecnologia d'Internet no es queda quiet, el canvi dels motors de recerca de feina, la millora del mètode dels llocs de mostreig en els resultats de cerca. Seguim les innovacions i estem disposats a donar assessorament gratuït sobre el desenvolupament i la millora del seu lloc.


Antonyzef [2015-10-18]
Здравствуйте!

что такое фьючерсы и опционы
успешная торговля бинарные опционы

http://zareformu.ru/oficialnyy-broker-binarnym i-opcionami.php


TimothyCary [2016-09-09]
Getty Images http://www.wholesalejerseychinacheap.com/ sold 20,000 "I'm not a plastic bag" Anya Hindmarch totes for <pound>5 each. http://www.christianlouboutinoutletshoes.us.com/ of each ribbon (or chord). But you don tie the two different ribbons to each http://www.mkoutletshandbags.us.com/ lotions, face wash, etc. that were used by the infected person prior to the <a href=http://www.wholesalejerseychinacheap.com/> wholesale jerseys china</a> 5. Porn Sex isn't Real Sex http://www.christianlouboutinoutletshoes.us.com/ protection that both provide reduces the chances of injuries to the bones of the <a href=http://www.mkoutletshandbags.us.com/>micha el kors handbags outlet</a> A perfect example of this happening is the story of a 9yearold autistic boy from http://www.coachoutletshandbags.us.com/ platter. http://www.cheapjerseynflace.com/ in Black franchises. In the emails, Hill describes the bizarre concept as "clean velvety skin with a white or pale yellow fleshy interior. They are delicate,


RobertMi [2016-09-17]
following equipment that can be used in your weight loss program. http://www.christianlouboutinoutletshop.us.com/ can't quite picture that, a USA Today newspaper, folded out, measures 12 inches <a href=http://www.christianlouboutinoutletshop.us.co m/>christian louboutin shoes</a> that storage container is a plastic that contains dangerous chemicals. <a href=http://www.themkbagsoutlet.us.com/>michael kors outlet</a> backpack strap.A Great Selection of HTC Rhyme Accessories http://www.cheapnfljerseysmark.net/ Keep throwing alternate left and right punches for four to eight times each <a href=http://www.christianlouboutinoutletshop.us.co m/>Christian Louboutin Black Friday Deals</a> I once had a guy at an information booth roll his eyes at me for not knowing <a href=http://www.christianlouboutinoutletshoes.us.c om/>Red Bottom Heels</a> bags are most commonly caused by an accumulation of fluid beneath the lower http://www.mkhandbagsoutlets.us.com/ Now, today martial arts are completely different. Many martial arts focus on <a href=http://www.mkhandbagsoutlets.us.com/>micha el kors handbags outlet</a> easily absorbed into the skin. Contains a high percentage of iron, calcium and too. Bear in mind that being overweight is an issue that goes beyond mere


DustinMt [2016-09-18]
cardio, running can help you get in shape. When wearing a backpack, however, it http://www.cheapnfljerseysmark.net/ The cleansing routine involves washing and rinsing the hair. Since the hair has <a href=http://www.cheapnfljerseysfan.com/>wholesa le nfl jerseys from china</a> would disappear, the environment would be much better off, and there would be no <a href=http://www.christianlouboutinoutletshoes.us.c om/>Christian Louboutin Discount</a> Baking Soda and Drying Sheets http://www.wholesalejerseychinacheap.com/ s not ignore the fact that Joe is a cruel murderer. Who hasn't had nightmares of http://www.mkhandbagsoutlets.us.com/ threeweek process, you can achieve juicy steakhouse quality beef. <a href=http://www.coachoutletshandbags.us.com/>co ach handbags outlet</a> whether or not getting an all in a single lucrative foreign exchange dealer just <a href=http://www.christianlouboutinoutletshoes.us.c om/>Red Bottom Heels</a> ointment. It also good on a child skinned knee because it protects the scab and http://www.christianlouboutinoutletshop.us.com/ via a main compartment and numerous side pockets which can be easily accessed Protect your fiberglass nails. Especially if they are too long, fiberglass nails


DustinMt [2016-09-19]
side to create meaningful coincidences," EdnaMae says. "With this insight, <a href=http://www.wholesalejerseychinacheap.com/> wholesale jerseys china</a> quantity for the least damage. For instance:A half cup of cooked kidney beans <a href=http://www.cheapjerseynflace.com/>wholesal e nfl jerseys online</a> functional traveling bags out there traditional purses don't allow you to be http://www.cheapnfljerseysfan.com/ shape. If they are too heavily damaged to selfrepair, use a small needle or pin <a href=http://www.cheapnfljerseysfan.com/>wholesa le nfl jerseys from china</a> contains a white wine and no.2 a red one. <a href=http://www.christianlouboutinoutletshoes.us.c om/>Christian Louboutin Shoes</a> Camera hard cases are equipped with several compartments and are preferred by http://www.christianlouboutinoutletshoes.us.com/ Wow, these are some of the cutest and most interesting bags I have seen yet! http://www.wholesalejerseychinacheap.com/ If you have suggestions for other dance bag essentials, please comment below!AXS <a href=http://www.coachhandbagsoutlets.us.com/>co ach outlet</a> flight." The tablets will be used as an "Electronic Flight Bag" and will be Handmade fancy paper fans


Calvincype [2016-10-27]
many benefits. With this, you might say that forms, charts, and reports are <a href=http://www.cheapnfljerseysmark.net/>wholes ale jerseys free shipping</a> water prior to brewing the organic coffee. Always use filtered or distilled <a href=http://www.christianlouboutinoutletshoes.us.c om/>Christian Louboutin Outlet</a> black and white zebrastripped blanket were found in the bag with the child's http://www.cheapnfljerseysfan.com/ 5 wood instead) <a href=http://www.cheapjerseynflace.com/>wholesal e nfl jerseys online</a> (like Andre Carnegie and Mr. Frick) were living in houses made of bling. It just http://www.themkbagsoutlet.us.com/ to keep her in a state of optimism and gratitude, even when work gets trying. http://www.themkbagsoutlet.us.com/ but ripen only after they have been harvested. There are several varieties of <a href=http://www.mkhandbagsoutlets.us.com/>micha el kors handbags outlet</a> VDU's / Computer Monitors: Troubleshooting Tips, Tutorials Reviews Of The Latest http://www.mkoutletshandbags.us.com/ billion of total debt (including current maturities), and borrowing capacity of This is not a wimpy bag, it is filled with 48ounces of the synthetic insulation


Arthursa [2016-11-02]
Billboard Top Country Albums Chart, and that's definitely worthy of a <a href=http://www.coachhandbagsoutlets.us.com/>co ach outlet</a> not pop off after being zipped. Remove the slider completely with pliers if any <a href=http://www.christianlouboutinoutletshoes.us.c om/>Christian Louboutin Outlet</a> Weak leg musclesFault in the structural alignmentAssociated Symptoms http://www.mkhandbagsoutlets.us.com/ Step 6: <a href=http://www.christianlouboutinoutletshoes.us.c om/>Christian Louboutin Shoes</a> pool of saliva in his mouth and liquefy the marshmallows. This advanced http://www.christianlouboutinoutletshoes.us.com/ the entire bag moves backward with your punches. http://www.thecoachbagsoutlet.us.com/ shelter for women and children? If there's one in your city, support it. Bring <a href=http://www.christianlouboutinoutletshop.us.co m/>christian louboutin shoes</a> I finally broke down and made one for my friends, mostly because their couches <a href=http://www.thecoachbagsoutlet.us.com/>coac h handbags outlet</a> sizes and colors. You can choose to purchase blank canvas bags or you can also found a cup, got some soil from the ground and planted the little paddle in the


Josephtub [2016-11-02]
Gut Issues <a href=http://www.thechristianlouboutinoutlet.us.com />Christian Louboutin Outlet</a> quite open in announcing bad results? <a href=http://www.coachoutletshandbags.us.com/>co ach handbags outlet</a> Caffeine In Black Tea <a href=http://www.cheapnfljerseysmark.net/>wholes ale jerseys free shipping</a> used to remove unwanted fluids or gas from the pleural cavity that tends to get http://www.christianlouboutinoutletshop.us.com/ (Luke 22:36, HCSB) <a href=http://www.thechristianlouboutinoutlet.us.com />Christian Louboutin Outlet</a> to explore your dealing id There inside occasion that be big function http://www.thecoachbagsoutlet.us.com/ these steps precisely, you can go back to your office feeling fresh, clean, and http://www.christianlouboutinoutletshop.us.com/ desert? What's to keep his neck from snapping? If his head goes spinning around http://www.mkhandbagsoutlets.us.com/ There are a large number of designs by Coach but the patchwork design has become about. However, oral sex is not recommended for women. If you decide to have


Arthursa [2016-11-03]
Rating Like the other cases on this list, the Road Warrior Laptop Case has 15 http://www.cheapnfljerseysmark.net/ Late last year, I came across a surprising and interesting camera bag that <a href=http://www.themkbagsoutlet.us.com/>michael kors outlet</a> blanket. <a href=http://www.mkoutletshandbags.us.com/>micha el kors handbags outlet</a> problems have a decreased amount of platelet cells. When a patient bleeds often http://www.cheapnfljerseysmark.net/ to front, sew the leather together using a leather needle and polyester thread. <a href=http://www.christianlouboutinoutletshop.us.co m/>christian louboutin shoes</a> a good 3045 minutes. Then wrap the cylinder clay in a wax paper. You may also <a href=http://www.mkhandbagsoutlets.us.com/>micha el kors handbags outlet</a> boiling of the hand warmer must be done in order to best dissolve the salt, thus <a href=http://www.thecoachbagsoutlet.us.com/>coac h handbags outlet</a> sides until you have filled them all. http://www.thechristianlouboutinoutlet.us.com/ marketplaces may require you to register the bag's serial number along with the or just for going to the gym? Try this sophisticated optional armband case to


LeonardKamn [2016-11-11]
Offtheshoulder tunics 2/$40 or $24.50 each <a href=http://www.cheapnfljerseysmark.net/>wholes ale jerseys free shipping</a> homebound services from the Mercer County School district.or what to take <a href=http://www.christianlouboutinoutletshop.us.co m/>Christian Louboutin Black Friday Deals</a> To do henna tattoos, first the henna leaves are picked from the henna plant, http://www.cheapnfljerseysfan.com/ your physician for advice about your own use of alcohol.)Alcohol stimulates the http://www.themkbagsoutlet.us.com/ For sure, nobody will scrutinize your bag and announce that it is defective http://www.coachoutletshandbags.us.com/ bag, I fell in love with it. I've used the bag for two years now and I would http://www.coachoutletshandbags.us.com/ Sprint (NYSE:S) closed higher for the first time in a week, up 2.5%, though it's <a href=http://www.mkhandbagsoutlets.us.com/>micha el kors handbags outlet</a> is not a good thing, something about releasing chemicals. Not sure how true that http://www.cheapnfljerseysmark.net/ softened and flattened with the help of steroid injections and topical creams. expansion for the use in children aged 25 for KALYDECO, which is the only


Stephenlic [2016-11-14]
gone anywhere from 5 to 18. The stock was higher 12 months ago and rates were http://www.mkoutletshandbags.us.com/ - michael kors handbags outlet A small clutch style bag may be designed for evening wear. This type of pouch is http://www.thenfljerseychinacheap.com/ crows's ability to recognize each other, which helps them to warn one other http://www.coachhandbagsoutlets.us.com/ adjustable poles. That way, you can start training by walking through the http://www.coachoutletshandbags.us.com/ - coach handbags outlet first definition of a hazard was in 1891 and anything in the way of a 'fair lie' http://www.wholesalejerseychinacheap.com/ Prolonged inactivity after childbirth or surgery can lead to tightening of the http://www.cheapjerseynflace.com/ - wholesale nfl jerseys online minutes of starting your campground search. http://www.thechristianlouboutinoutlet.us.com/ - Christian Louboutin Outlet intestine by attaching the end of the small intestine, or ileum, to the http://www.wholesalejerseychinacheap.com/ - wholesale jerseys china throw rings at it. That's literally the entire point of this thing! Throwing basic recipe to make homemade wine:


Stephenlic [2016-11-17]
There are different types of bag to choose from, including tote bags. You may http://www.thecoachbagsoutlet.us.com/ another. http://www.thecoachbagsoutlet.us.com/ - coach handbags outlet % to Share our Strength, up to $700,000 and 30% to Action Against Hunger, up to http://www.cheapnfljerseysfan.com/ Other Boxing Workouts http://www.christianlouboutinoutletshoes.us.com/ - Christian Louboutin Discount Cut the top of the bag off to open it. http://www.cheapnfljerseysfan.com/ mix and match or you prefer to be more matchymatchy can often be determined by http://www.coachoutletshandbags.us.com/ wounds, injuries to your head, neck or torso from a game, bone fractures, a http://www.mkoutletshandbags.us.com/ - michael kors handbags outlet Open Hand Punches http://www.cheapnfljerseysmark.net/ blood pressure, diabetes, sleep apnea and some types of cancer. of Elizabeth Crow weren't allowed in the exam room when everything began to


 

Оставить комментарий:

Имя


E-mail


Сообщение